BZOJ4066 简单题
Description
你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:
命令 | 参数限制 | 内容 |
1 x y A | 1<=x,y<=N,A是正整数 | 将格子x,y里的数字加上A |
2 x1 y1 x2 y2 | 1<=x1<= x2<=N
1<=y1<= y2<=N |
输出x1 y1 x2 y2这个矩形内的数字和 |
3 | 无 | 终止程序 |
Input
输入文件第一行一个正整数N。
接下来每行一个操作。每条命令除第一个数字之外,
均要异或上一次输出的答案last_ans,初始时last_ans=0。
Output
对于每个2操作,输出一个对应的答案。
Sample Input
4
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3
Sample Output
3
5
HINT
数据规模和约定
1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。
样例解释见OJ2683
新加数据一组,但未重测—-2015.05.24
我终于过了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
由于内存很紧,我们不能用树套树来做,但k-d树还是可以的。
考虑出题人可能将k-d树的形态搞得很糟糕,我们可以定期重建整棵树
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<algorithm> #define rep(s,t) for(int i=s;i<=t;i++) #define ren for(int i=first[x];i!=-1;i=next[i]) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=200010; int n,D,lastans; struct Point { int d[2],mx[2],mn[2],v,l,r,sum; bool operator == (const Point& ths) const {return d[0]==ths.d[0]&&d[1]==ths.d[1];} bool operator < (const Point& ths) const {return d[D]<ths.d[D];} }p[maxn]; int in(int& x1,int& y1,int& x2,int& y2,int& X1,int& Y1,int& X2,int& Y2) {return x1<=X1&&x2>=X2&&y1<=Y1&&y2>=Y2;} int out(int& x1,int& y1,int& x2,int& y2,int& X1,int& Y1,int& X2,int& Y2) {return x1>X2||x2<X1||y1>Y2||y2<Y1;} struct Kd_Tree { Point t[maxn],now; int rt,cnt; Kd_Tree() {t[0].mn[0]=t[0].mn[1]=2e9;t[0].mx[0]=t[0].mx[1]=-2e9;} void maintain(int k) { int l=t[k].l,r=t[k].r; rep(0,1) t[k].mn[i]=min(t[k].d[i],min(t[l].mn[i],t[r].mn[i])),t[k].mx[i]=max(t[k].d[i],max(t[l].mx[i],t[r].mx[i])); t[k].sum=t[l].sum+t[r].sum+t[k].v; } void insert(int& k,int d) { if(!k) k=++cnt,t[k].d[0]=t[k].mx[0]=t[k].mn[0]=now.d[0],t[k].d[1]=t[k].mx[1]=t[k].mn[1]=now.d[1]; if(now==t[k]) { t[k].v+=now.v;t[k].sum+=now.v; return; } if(now.d[d]<t[k].d[d]) insert(t[k].l,d^1); else insert(t[k].r,d^1); maintain(k); } int query(int k,int x1,int y1,int x2,int y2) { if(!k) return 0; if(in(x1,y1,x2,y2,t[k].mn[0],t[k].mn[1],t[k].mx[0],t[k].mx[1])) return t[k].sum; if(out(x1,y1,x2,y2,t[k].mn[0],t[k].mn[1],t[k].mx[0],t[k].mx[1])) return 0; int ret=0; if(in(x1,y1,x2,y2,t[k].d[0],t[k].d[1],t[k].d[0],t[k].d[1])) ret+=t[k].v; ret+=query(t[k].l,x1,y1,x2,y2)+query(t[k].r,x1,y1,x2,y2); return ret; } int build(int l,int r,int d) { if(l>r) return 0; int mid=l+r>>1;D=d;nth_element(p+l,p+mid,p+r+1); t[mid]=p[mid];t[mid].l=build(l,mid-1,d^1);t[mid].r=build(mid+1,r,d^1); maintain(mid);return mid; } }T; int main() { n=read();int ToT=0; while(1) { int tp=read(); if(tp==3) break; else if(tp==1) { int x=read()^lastans,y=read()^lastans; T.now.d[0]=x;T.now.d[1]=y; T.now.v=T.now.sum=read()^lastans; T.insert(T.rt,0); if(++ToT==7000) { rep(1,T.cnt) p[i]=T.t[i]; T.rt=T.build(1,T.cnt,0);ToT=0; } } else { int x=read()^lastans,y=read()^lastans,x2=read()^lastans,y2=read()^lastans; printf("%d\n",lastans=T.query(T.rt,x,y,x2,y2)); } } return 0; }