GDCPC2021 K - Kera's line segment(二维树状数组)

题目

source

题解

将区间[L,R]视作坐标系中的点(L,R),那么添加线段[L,R]就是在坐标系上添加点(L,R);查询[L,R]就是查询范围{(l,r)|l >= L and r <= R}对应的矩形范围内的最大值和最小值的差值。由于只有添加没有删除,可以使用二维树状数组;或者使用树套树,支持单点修改区间查询。

#include<iostream>
#include<cstring>
using namespace std;
const int N = 3000 + 10;
const int M = 998244353;
typedef long long ll;
#define endl '\n'
int mx[N][N];
int mi[N][N];

int lowbit(int x) {
	return x&-x;
}

void upd(int l, int r, int val) {
	int pl = N - l;
	while(pl < N) {
		int pr = r;
		while(pr < N) {
			mx[pl][pr] = max(mx[pl][pr], val);
			mi[pl][pr] = min(mi[pl][pr], val);
			pr += lowbit(pr);
		} 	
		pl += lowbit(pl);
	}
}

int que(int l, int r) {
	int rmx = 0;
	int rmi = 0x3f3f3f3f;
	int pl = N - l;
	while(pl) {
		int pr = r;
		while(pr) {
			rmx = max(mx[pl][pr], rmx);
			rmi = min(mi[pl][pr], rmi);
			pr -= lowbit(pr);
		}
		pl -= lowbit(pl);
	}
	if(rmi == 0x3f3f3f3f) return 0;
	else return rmx - rmi;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	memset(mi, 0x3f, sizeof mi);
	memset(mx, 0, sizeof mx);
	int n, m;
	cin >> n >> m;
	for(int i = 1; i <= n; i++) {
		int l, r, val;
		cin >> l >> r >> val;
		upd(l, r, val);
	}
	int ans = 0;
	while(m--) {
		int op, a, b;
		cin >> op >> a >> b;
		int l = a ^ ans, r = b ^ ans;
		if(op == 1) {
			int val;
			cin >> val;
			upd(l, r, val);
		} else {
			ans = que(l, r);
			cout << ans << endl;
		}
	}
}
posted @ 2021-07-06 22:24  limil  阅读(223)  评论(3编辑  收藏  举报