I - Colonial Mansions Gym - 101962I[二分+線段樹]
阿新 • • 發佈:2018-11-07
題意:給出一個有n個數字的數列,有兩種操作
- 1 x H 將x位置的數字改為H
- 2 x H 從x出發在每次數字相差不超過H的條件下可以向左右拓展多少個
思路:可以維護一個差分序列,這裡維護的是相鄰兩個數字的差值(為了條件2),然後通過線段樹去維護這個差值,當更新的時候需要更新兩個差值,i - 1和i,因為更改i位置的數字會影響它本身與後面的差值,同樣會影響他前面數字與它的差值,所以每次更新需要線段樹兩次單點更新,查詢向左右分別拓展了多少的時候可以二分,因為距離具有單調性,查詢某個區間的最大值(差分後為最大差值),如果這個最大值滿足條件再拓展區間即可。複雜度O( )。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define met(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
#define int ll
struct TreeNode {
int l, r, MAX, MIN;
} treeNode[maxn << 2];
int a[maxn], hh[maxn];
void push_up(int root) {
treeNode[root].MAX = max(treeNode[root << 1].MAX, treeNode[root << 1 | 1].MAX);
treeNode[root].MIN = min(treeNode[root << 1].MIN, treeNode[root << 1 | 1].MIN);
}
void buildTree(int root, int l, int r) {
treeNode[root].l = l;
treeNode[root].r = r;
if(l == r) {
treeNode[root].MAX = treeNode[root].MIN = hh[l];
return;
}
int mid = (l + r) >> 1;
buildTree(root << 1, l, mid);
buildTree(root << 1 | 1, mid + 1, r);
push_up(root);
}
void upd(int root, int pos, int x) {
if(treeNode[root].l == treeNode[root].r) {
treeNode[root].MAX = treeNode[root].MIN = x;
return;
}
int mid = (treeNode[root].l + treeNode[root].r) >> 1;
if(pos <= mid) upd(root << 1, pos, x);
else upd(root << 1 | 1, pos, x);
push_up(root);
}
int MAX, MIN;
void query(int root, int l, int r) {
if(l > r) {
MAX = 0;
return;
}
if(treeNode[root].l == l && treeNode[root].r == r) {
MAX = max(MAX, treeNode[root].MAX);
MIN = min(MIN, treeNode[root].MIN);
return;
}
int mid = (treeNode[root].l + treeNode[root].r) >> 1;
if(r <= mid) query(root << 1, l, r);
else if(l > mid) query(root << 1 | 1, l, r);
else {
query(root << 1, l, mid);
query(root << 1 | 1, mid + 1, r);
}
}
int divide(int l, int r, int flag, int x, int h) {
int res = 0;
while(l <= r) {
int mid = (l + r) >> 1;
MAX = -inf; MIN = inf;
if(flag == 0) query(1, mid, x - 1);
else query(1, x, mid - 1);
if(MAX <= h) {
if(flag == 0) {
res = max(x - mid, res);
r = mid - 1;
} else {
res = max(mid - x, res);
l = mid + 1;
}
} else {
if(flag == 0) {
l = mid + 1;
} else {
r = mid - 1;
}
}
}
return res;
}
#undef int
int main() {
#define int ll
int n, q;
while(~scanf("%lld%lld", &n, &q)) {
rep(i, 1, n) scanf("%lld", &a[i]);
rep(i, 1, n) {
hh[i] = abs(a[i] - a[i + 1]);
}
hh[n] = 0;
buildTree(1, 1, n);
int com, x, h;
while(q--) {
scanf("%lld%lld%lld", &com, &x, &h);
if(com == 1) {
a[x] = h;
hh[x] = abs(a[x] - a[x + 1]);
upd(1, x, hh[x]);
if(x - 1 > 0) {
hh[x - 1] = abs(a[x - 1] - a[x]);
upd(1, x - 1, hh[x - 1]);
}
} else {
int ans = 1;
ans += divide(x, n, 1, x, h);
ans += divide(1, x, 0, x, h);
printf("%lld\n", ans);
}
}
}
return 0;
}