bzoj4066 简单题 kdtree

版权声明:虽然是个蒟蒻但是转载还是要说一声的哟 https://blog.csdn.net/jpwang8/article/details/84962698

Description

你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:

1 x y A 将格子x,y里的数字加上A
2 x1 y1 x2 y2 输出x1 y1 x2 y2这个矩形内的数字和
强制在线

1<=N<=500000,操作数不超过200000个,内存限制20M

Solution


真的是简单题。。
不在线可以cdq,在线就kdtree咯
一个小技巧就是定期重构kdtree,或者用平衡因子来判定也行

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define lowbit(x) (x&-x)

const int N=300005;

struct treeNode {int sum,val,son[2],p[2],mx[2],mn[2];} t[N];

int wjp,tot;

int read() {
	int x=0,v=1; char ch=getchar();
	for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
	for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
	return x*v;
}

void push_up(int now) {
	t[now].sum=t[t[now].son[0]].sum+t[t[now].son[1]].sum+t[now].val;
	t[now].mx[0]=t[now].mn[0]=t[now].p[0];
	t[now].mx[1]=t[now].mn[1]=t[now].p[1];
	if (t[now].son[0]) {
		t[now].mx[0]=std:: max(t[t[now].son[0]].mx[0],t[now].mx[0]);
		t[now].mx[1]=std:: max(t[t[now].son[0]].mx[1],t[now].mx[1]);
		t[now].mn[0]=std:: min(t[t[now].son[0]].mn[0],t[now].mn[0]);
		t[now].mn[1]=std:: min(t[t[now].son[0]].mn[1],t[now].mn[1]);
	}
	if (t[now].son[1]) {
		t[now].mx[0]=std:: max(t[t[now].son[1]].mx[0],t[now].mx[0]);
		t[now].mx[1]=std:: max(t[t[now].son[1]].mx[1],t[now].mx[1]);
		t[now].mn[0]=std:: min(t[t[now].son[1]].mn[0],t[now].mn[0]);
		t[now].mn[1]=std:: min(t[t[now].son[1]].mn[1],t[now].mn[1]);
	}
}

bool cmp(treeNode a,treeNode b) {
	return (a.p[wjp]==b.p[wjp])?(a.p[!wjp]<b.p[!wjp]):(a.p[wjp]<b.p[wjp]);
}

int build(int l,int r,int R) {
	int mid=(l+r)>>1; wjp=R;
	std:: nth_element(t+l,t+mid,t+r+1,cmp);
	t[mid].son[0]=t[mid].son[1]=0;
	if (l<mid) t[mid].son[0]=build(l,mid-1,!R);
	if (mid<r) t[mid].son[1]=build(mid+1,r,!R);
	push_up(mid); return mid;
}

bool check(int now,int x1,int y1,int x2,int y2) {
	if (x2<t[now].mn[0]||x1>t[now].mx[0]) return false;
	if (y2<t[now].mn[1]||y1>t[now].mx[1]) return false;
	return true;
}

int query(int now,int x1,int y1,int x2,int y2,int R) {
	if (t[now].mn[0]>=x1&&t[now].mx[0]<=x2&&t[now].mn[1]>=y1&&t[now].mx[1]<=y2) return t[now].sum;
	int res=0;
	if (t[now].p[0]>=x1&&t[now].p[0]<=x2&&t[now].p[1]>=y1&&t[now].p[1]<=y2) res+=t[now].val;
	if (check(t[now].son[0],x1,y1,x2,y2)) res+=query(t[now].son[0],x1,y1,x2,y2,!R);
	if (check(t[now].son[1],x1,y1,x2,y2)) res+=query(t[now].son[1],x1,y1,x2,y2,!R);
	return res;
}

void ins(int now,int R) {
	if (t[now].p[0]==t[tot].p[0]&&t[now].p[1]==t[tot].p[1]) {
		t[now].val+=t[tot].val;
		t[now].sum+=t[tot].val;
		tot--; push_up(now);
		return ;
	}
	int d=t[tot].p[R]>t[now].p[R];
	if (!t[now].son[d]) t[now].son[d]=tot;
	else ins(t[now].son[d],!R);
	push_up(now);
}

int main(void) {
	freopen("data.in","r",stdin);
	freopen("myp.out","w",stdout);
	int root=0; read();
	for (int lastans=0,cnt=0;;) {
		int opt=read(); if (opt==3) break;
		if (opt==1) {
			int x=read()^lastans;
			int y=read()^lastans;
			int v=read()^lastans;
			t[++tot]=(treeNode) {v,v,{0,0},{x,y},{x,y},{x,y}};
			if (!root) {
				root=tot;
				push_up(tot);
			} else ins(root,0);
		} else {
			int x1=read()^lastans;
			int y1=read()^lastans;
			int x2=read()^lastans;
			int y2=read()^lastans;
			printf("%d\n", lastans=query(root,x1,y1,x2,y2,0));
		}
		if (++cnt==60000) root=build(1,tot,0),cnt=0;
		lastans=0;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/84962698