声明:使用了latex,可能会有部分加载速度慢
这题的单点修改,区间查询,首先考虑线段树。
单点修改的 change 很好写,难点在于区间查询。
将题目中的式子分类讨论:
①:得
。
②:得
。
③:得
。
④:得
。
由于当①和②是正数时,③和④不如①和②,反之亦然。
所以线段树中需要存4个元素: 的最大值和最小值,
的最大值和最小值。
查询也需分类讨论:
若 ,则
return ask(p * 2, l, r);
若 ,则
return ask(p * 2 + 1, l, r);
否则,取两者的最值。
最后输出时2将得到的结构体拆开,按照上面的格式输出,取最大值。
完整代码:
#include <bits/stdc++.h>
using namespace std;
struct node{
long long l, r, xya, xyb, x_ya, x_yb;
}t[800005];
long long n, q;
node pushup(int aa, int ab, node p, node h){
return {aa, ab, max(p.xya, h.xya), min(p.xyb, h.xyb), max(p.x_ya, h.x_ya), min(p.x_yb, h.x_yb)};
}
void build(long long p, long long l, long long r){
t[p].l = l;
t[p].r = r;
if(l==r){
return;
}
long long mid = (l + r) >> 1;
build(p * 2, l, mid);
build(p * 2 + 1, mid + 1, r);
}
void change(long long p, long long i, long long g, long long h){
if(t[p].l==t[p].r){
t[p] = {t[p].l, t[p].r, g + h, g + h, g - h, g - h};
return;
}
long long mid = (t[p].l + t[p].r) >> 1;
if(i<=mid){
change(p * 2, i, g, h);
}else{
change(p * 2 + 1, i, g, h);
}
t[p] = pushup(t[p].l, t[p].r, t[p * 2], t[p * 2 + 1]);
}
node ask(long long p, long long l, long long r){
if(l<=t[p].l&&t[p].r<=r){
return t[p];
}
long long mid = (t[p].l + t[p].r) >> 1;
if(r<=mid){
return ask(p * 2, l, r);
}
if(l>mid){
return ask(p * 2 + 1, l, r);
}
return pushup(0, 0, ask(p * 2, l, r), ask(p * 2 + 1, l, r));
}
int main(){
scanf("%lld %lld", &n, &q);
build(1, 1, n);
for(long long i = 1;i<=n;i++){
long long x, y;
scanf("%lld %lld", &x, &y);
change(1, i, x, y);
}
while(q--){
long long op;
scanf("%lld", &op);
if(op==1){
long long i, x, y;
scanf("%lld %lld %lld", &i, &x, &y);
change(1, i, x, y);
}else{
long long l, r, x, y;
scanf("%lld %lld %lld %lld", &l, &r, &x, &y);
node t = ask(1, l, r);
printf("%lld\n", max({t.xya - (x + y), (x + y) - t.xyb, t.x_ya - (x - y), (x - y) - t.x_yb}));
}
}
return 0;
}

被折叠的 条评论
为什么被折叠?



