|
|
|
|
##[$POJ$ $3264$ $Balanced$ $Lineup$](http://poj.org/problem?id=3264)
|
|
|
|
|
|
|
|
|
|
### 一、大致题意
|
|
|
|
|
给定一组序列编号从$1-n$, 有$q$个询问, 每次询问$[l, r]$区间的最大值与最小值的 **差值**.
|
|
|
|
|
|
|
|
|
|
### 二、解题思路
|
|
|
|
|
|
|
|
|
|
- 单点修改构建数据结构
|
|
|
|
|
- 比较适合树状数组,代码更简单
|
|
|
|
|
- 如果使用线段树,那么不需要$pushdown$+懒标记优化,一切递归到底,慢就慢吧
|
|
|
|
|
- 区间查询,求区间最大+最小值
|
|
|
|
|
|
|
|
|
|
### 三、树状数组解法
|
|
|
|
|
```cpp {.line-numbers}
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
|
|
const int INF = 0x3f3f3f3f;
|
|
|
|
|
using namespace std;
|
|
|
|
|
const int N = 50010;
|
|
|
|
|
|
|
|
|
|
int a[N];
|
|
|
|
|
int n, q;
|
|
|
|
|
|
|
|
|
|
// 树状数组模板
|
|
|
|
|
int c1[N], c2[N]; // c1:维护最大值,c2:维护最小值
|
|
|
|
|
|
|
|
|
|
int lowbit(int x) {
|
|
|
|
|
return x & -x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void update(int x, int d) {
|
|
|
|
|
for (int i = x; i < N; i += lowbit(i)) c1[i] = max(c1[i], d), c2[i] = min(c2[i], d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int query(int x, int y) {
|
|
|
|
|
int mx = 0, mi = INF;
|
|
|
|
|
while (y >= x) { // 右侧到左侧
|
|
|
|
|
mx = max(mx, a[y]), mi = min(mi, a[y]); // 每次最后侧的点参加评比
|
|
|
|
|
|
|
|
|
|
for (--y; y - x >= lowbit(y); y -= lowbit(y)) // 从x~y-1检查每个片断
|
|
|
|
|
mx = max(mx, c1[y]), mi = min(mi, c2[y]);
|
|
|
|
|
}
|
|
|
|
|
return mx - mi;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
#ifndef ONLINE_JUDGE
|
|
|
|
|
freopen("POJ3264.in", "r", stdin);
|
|
|
|
|
#endif
|
|
|
|
|
memset(c1, 0, sizeof c1);
|
|
|
|
|
memset(c2, 0x3f, sizeof c2); // 最小值,需要先设置最大,最大值默认的就是0,不需要设置
|
|
|
|
|
scanf("%d %d", &n, &q);
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i <= n; i++) {
|
|
|
|
|
scanf("%d", &a[i]);
|
|
|
|
|
update(i, a[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (q--) {
|
|
|
|
|
int a, b;
|
|
|
|
|
scanf("%d %d", &a, &b);
|
|
|
|
|
printf("%d\n", query(a, b));
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 四、线段树解法
|
|
|
|
|
```cpp {.line-numbers}
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
const int INF = 0x3f3f3f3f;
|
|
|
|
|
const int N = 50010;
|
|
|
|
|
int a[N];
|
|
|
|
|
|
|
|
|
|
struct Node {
|
|
|
|
|
int l, r, mx, mi;
|
|
|
|
|
} tr[N << 2];
|
|
|
|
|
|
|
|
|
|
int mx, mi;
|
|
|
|
|
void pushup(int u) {
|
|
|
|
|
tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx);
|
|
|
|
|
tr[u].mi = min(tr[u << 1].mi, tr[u << 1 | 1].mi);
|
|
|
|
|
}
|
|
|
|
|
void build(int u, int l, int r) {
|
|
|
|
|
tr[u].l = l, tr[u].r = r; // POJ对于tr[u]={l,r}报编译错误,编译器版本太低,需要手动实现构造函数
|
|
|
|
|
|
|
|
|
|
if (l == r) {
|
|
|
|
|
tr[u].mx = a[l], tr[u].mi = a[l];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int mid = (l + r) >> 1;
|
|
|
|
|
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
|
|
|
|
|
pushup(u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void query(int u, int l, int r) {
|
|
|
|
|
if (l <= tr[u].l && r >= tr[u].r) {
|
|
|
|
|
mx = max(mx, tr[u].mx), mi = min(mi, tr[u].mi);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int mid = (tr[u].l + tr[u].r) >> 1;
|
|
|
|
|
|
|
|
|
|
if (l <= mid) query(u << 1, l, r);
|
|
|
|
|
if (r > mid) query(u << 1 | 1, l, r);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
#ifndef ONLINE_JUDGE
|
|
|
|
|
freopen("POJ3264.in", "r", stdin);
|
|
|
|
|
#endif
|
|
|
|
|
// 加快读入
|
|
|
|
|
ios::sync_with_stdio(false), cin.tie(0);
|
|
|
|
|
int n, q;
|
|
|
|
|
cin >> n >> q;
|
|
|
|
|
for (int i = 1; i <= n; i++) cin >> a[i];
|
|
|
|
|
build(1, 1, n);
|
|
|
|
|
|
|
|
|
|
while (q--) {
|
|
|
|
|
mx = -INF, mi = INF;
|
|
|
|
|
int l, r;
|
|
|
|
|
cin >> l >> r;
|
|
|
|
|
query(1, l, r);
|
|
|
|
|
printf("%d\n", mx - mi);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
```
|