2020 wannafly camp day5 I Practice for KD Tree —— 二维线段树

题目链接:点我啊╭(╯^╰)╮

题目大意:

     m 1 m1 m1 次矩阵加后, m 2 m2 m2 次查询矩阵最大值

解题思路:

     m 1 m1 m1 次操作可以直接差分做
    问题在于怎么查询矩阵最大值
    用二维线段树或者四叉树都可以做
    这里给了一份比较好的模板

核心:线段树套线段树

// https://pintia.cn/problem-sets/1217641604302602240/problems/1217642214674497544
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
using pii = pair <int,int>;
const int maxn = 2e3 + 5;
int n, m1, m2;
ll a[maxn][maxn];
struct seg{
	ll t[maxn<<2];
	void build(int L, int l, int r, int rt){
		if(l == r){
			t[rt] = a[L][r];
			return;
		}
		int m = l + r >> 1;
		build(L, l, m, rt<<1);
		build(L, m+1, r, rt<<1|1);
		t[rt] = max(t[rt<<1], t[rt<<1|1]);
	}
	void update(int L, int R, ll x, int l, int r, int rt){
		t[rt] = x;
		if(l==L && r==R){
//			lz[rt] = x;
			return;
		}
		int m = l + r >> 1;
		if(m >= R) update(L, R, x, l, m, rt<<1);
		else if(L > m) update(L, R, x, m+1, r, rt<<1|1);
		else update(L, m, x, l, m, rt<<1), \
			 update(m+1, R, x, m+1, r, rt<<1|1);
		t[rt] = max(t[rt<<1], t[rt<<1|1]);
	}
	ll query(int L, int R, int l, int r, int rt, ll sum){
		if(l==L && r==R) return t[rt];
		int m = l + r >> 1;
		if(m >= R) return query(L, R, l, m, rt<<1, sum);
		else if(L > m) return query(L, R, m+1, r, rt<<1|1, sum);
		else return max( query(L, m, l, m, rt<<1, sum), \
			 			 query(m+1, R, m+1, r, rt<<1|1, sum) );
	}
} t[maxn<<2], lz[maxn<<2];

void merge(seg &p, seg &p1, seg &p2, int L, int R, int l, int r, int rt){
	if(l>R || r<L) return; 
	p.t[rt] = max(p1.t[rt], p2.t[rt]);
	if(l == r) return;
	int m = l + r >> 1;
	merge(p, p1, p2, L, R, l, m, rt<<1);
	merge(p, p1, p2, L, R, m+1, r, rt<<1|1);
}

void build(int l, int r, int rt){
	if(l == r){
		t[rt].build(l, 1, n, 1);
		return;
	}
	int m = l + r >> 1;
	build(l, m, rt<<1);
	build(m+1, r, rt<<1|1);
	merge(t[rt], t[rt<<1], t[rt<<1|1], 1, n, 1, n, 1);
}
void update(int x, int y, int xx, int yy, ll v, int l, int r, int rt){
	if(l==x && r==xx){
		t[rt].update(y, yy, v, 1, n, 1);
//		lz[rt].update(y, yy, v, 1, n, 1);
		return;
	}
	int m = l + r >> 1;
	if(m >= xx) update(x, y, xx, yy, v, l, m, rt<<1);
	else if(x > m) update(x, y, xx, yy, v, m+1, r, rt<<1|1);
	else update(x, y, m, yy, v, l, m, rt<<1), \
		 update(m+1, y, xx, yy, v, m+1, r, rt<<1|1);
	merge(t[rt], t[rt<<1], t[rt<<1|1], y, yy, 1, n, 1);
}

ll query(int x, int y, int xx, int yy, int l, int r, int rt, ll sum){
	if(l==x && r==xx) return t[rt].query(y, yy, 1, n, 1, 0);
//	sum += lz[rt].query(y, yy, 1, n, 1, 0);
	int m = l + r >> 1;
	if(m >= xx) return query(x, y, xx, yy, l, m, rt<<1, sum);
	else if(x > m) return query(x, y, xx, yy, m+1, r, rt<<1|1, sum);
	else return max( query(x, y, m, yy, l, m, rt<<1, sum), \
					 query(m+1, y, xx, yy, m+1, r, rt<<1|1, sum) );
}

int main() {
	scanf("%d%d%d", &n, &m1, &m2);
	int x1, x2, y1, y2, w;
	for(int i=1; i<=m1; i++){
		scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &w);
		a[x1][y1] += w, a[x2+1][y2+1] += w;
		a[x1][y2+1] -= w, a[x2+1][y1] -= w;
	}
	for(int i=1; i<=n; i++)
		for(int j=1; j<=n; j++){
			a[i][j] += a[i][j-1] + a[i-1][j] - a[i-1][j-1];
//			update(i, j, i, j, a[i][j], 1, n, 1);
		}
	build(1, n, 1);
	while(m2--){
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		printf("%lld\n", query(x1, y1, x2, y2, 1, n, 1, 0));
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值