abc437f

声明:使用了latex,可能会有部分加载速度慢

这题的单点修改,区间查询,首先考虑线段树。

单点修改的 change 很好写,难点在于区间查询。

将题目中的式子分类讨论:

x_1\le x_2,y_1\le y_2:得 x_2+y_2-x_1-y_1

x_1\le x_2,y_1>y_2:得 x_2-y_2-x_1+y_1

x_1>x_2,y_1\le y_2:得 -(x_2-y_2)+x_1-y_1

x_1>x_2,y_1>y_2:得 -(x_2+y_2)+x_1+y_1

由于当①和②是正数时,③和④不如①和②,反之亦然。

所以线段树中需要存4个元素:x_2+y_2 的最大值和最小值,x_2-y_2 的最大值和最小值。

查询也需分类讨论:

若 r \le mid,则

return ask(p * 2, l, r);

若 l>mid,则

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;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值