BZOJ 1176: [Balkan2007]Mokia KDtree
Description
维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.
Input
第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小
接下来每行为一下三种输入之一(不包含引号):
"1 x y a"
"2 x1 y1 x2 y2"
"3"
输入1:你需要把(x,y)(第x行第y列)的格子权值增加a
输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出
输入3:表示输入结束
Output
对于每个输入2,输出一行,即输入2的答案
题解:写一个 KDtree 即可.
#include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin), freopen(s".out","w",stdout) #define maxn 1000000 #define mid ((l+r)>>1) using namespace std; int d,root,tot, W; struct Node { int ch[2],p[2],minv[2],maxv[2],w,sumv; }t[maxn]; bool cmp(Node a,Node b) { return a.p[d]==b.p[d]?a.p[d^1]<b.p[d^1]:a.p[d]<b.p[d]; } int isin(int x,int x1,int y1,int x2,int y2) { if(x1 <= t[x].minv[0] && x2 >= t[x].maxv[0] && y1 <= t[x].minv[1] && y2 >= t[x].maxv[1]) return 1; else return 0; } int isout(int x,int x1,int y1,int x2,int y2) { if(x1 > t[x].maxv[0] || x2 < t[x].minv[0] || y1 > t[x].maxv[1] || y2 < t[x].minv[1]) return 1; else return 0; } void pushup(int x,int y) { for(int i=0;i<2;++i) { t[x].minv[i]=min(t[x].minv[i], t[y].minv[i]); t[x].maxv[i]=max(t[x].maxv[i], t[y].maxv[i]); } t[x].sumv+=t[y].sumv; } void insert(int &x,int o) { if(!x) { x = tot; t[tot].minv[0]=t[tot].maxv[0]=t[tot].p[0]; t[tot].minv[1]=t[tot].maxv[1]=t[tot].p[1]; t[tot].sumv=t[tot].w; t[tot].ch[0]=t[tot].ch[1]=0; return; } d=o; if(cmp(t[tot], t[x]) == 1) { insert(t[x].ch[0], o^1); pushup(x, tot); } else { insert(t[x].ch[1],o^1); pushup(x, tot); } } int query(int x,int x1,int y1,int x2,int y2) { if(isout(x, x1, y1, x2, y2) || !x) return 0; if(isin(x, x1, y1, x2, y2)) return t[x].sumv; int tmp=0; if(t[x].p[0] >= x1 && t[x].p[0] <= x2 && t[x].p[1] >= y1 && t[x].p[1] <= y2) tmp += t[x].w; if(t[x].ch[0]) tmp += query(t[x].ch[0], x1, y1, x2, y2); if(t[x].ch[1]) tmp += query(t[x].ch[1], x1, y1, x2, y2); return tmp; } int build(int l,int r,int o) { d=o; nth_element(t+l,t+mid,t+1+r,cmp); t[mid].minv[0]=t[mid].maxv[1]=t[mid].p[0]; t[mid].minv[1]=t[mid].maxv[1]=t[mid].p[1]; t[mid].sumv = t[mid].w; t[mid].ch[0]=t[mid].ch[1]=0; if(mid > l) { t[mid].ch[0] = build(l, mid - 1, o ^ 1); pushup(mid, t[mid].ch[0]); } if(r > mid) { t[mid].ch[1] = build(mid + 1, r, o ^ 1); pushup(mid, t[mid].ch[1]); } return mid; } int main() { // setIO("input"); int S,opt,i,j,x,y,k,root = 0 ,a,b,c,d,ii=0; scanf("%d%d",&W,&S); for(ii=1;;++ii) { scanf("%d",&opt); if(opt==1) { scanf("%d%d%d",&x,&y,&k); ++tot; t[tot].p[0]=x, t[tot].p[1]=y, t[tot].w = k; insert(root, 0); } if(opt==2) { scanf("%d%d%d%d",&a,&b,&c,&d); printf("%d\n",query(root, a, b, c, d)); } if(opt==3) break; } return 0; }