题意:给出一个有n个数字的数列,有两种操作
思路:可以维护一个差分序列,这里维护的是相邻两个数字的差值(为了条件2),然后通过线段树去维护这个差值,当更新的时候需要更新两个差值,i - 1和i,因为更改i位置的数字会影响它本身与后面的差值,同样会影响他前面数字与它的差值,所以每次更新需要线段树两次单点更新,查询向左右分别拓展了多少的时候可以二分,因为距离具有单调性,查询某个区间的最大值(差分后为最大差值),如果这个最大值满足条件再拓展区间即可。复杂度O( n l o g n l o g n nlognlogn nlognlogn)。
a c c o d e : ac\ code: ac code:
#include
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;
}