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
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3
Sample Output
3
5
5
HINT
数据规模和约定
1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。
题解Here!
看完题二话不说一个树状数组$+Treap$。
然后就$MLE$了。。。
回头看题:怎么只有$20M$???
这。。。强制在线。。。只好$K-D Tree$。。。
其实有一道弱化版:
BZOJ1176: [Balkan2007]Mokia
但是这道题却只能用$K-D Tree$。。。
感觉$K-D Tree$要变成替罪羊树了。。。
还拍平重建。。。
附代码:
#include<iostream> #include<algorithm> #include<cstdio> #define MAXN 200010 #define MAX (1LL<<30) #define Alpha 0.75 using namespace std; int n,m; int root,size=0,l1,r1,l2,r2; int top,recycle[MAXN]; bool sort_flag=false; struct Point{ int x,y,z; friend bool operator <(const Point &p,const Point &q){ if(sort_flag)return p.y<q.y; return p.x<q.x; } }point[MAXN],now; struct Tree{ Point point; int maxx,maxy,minx,miny,val,sum,size,lson,rson; }a[MAXN]; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } inline bool check_inside(int x1,int y1,int x2,int y2){ return ((l1<=x1&&x2<=l2)&&(r1<=y1&&y2<=r2)); } inline bool check_outside(int x1,int y1,int x2,int y2){ return ((x2<l1||x1>l2)||(y2<r1||y1>r2)); } inline int newnode(const Point &p){ int rt; if(top)rt=recycle[top--]; else rt=++size; a[rt].point=p; a[rt].maxx=a[rt].minx=p.x; a[rt].maxy=a[rt].miny=p.y; a[rt].val=a[rt].sum=p.z; a[rt].lson=a[rt].rson=0; a[rt].size=1; return rt; } inline void pushup(int rt){ int lson=a[rt].lson,rson=a[rt].rson; a[rt].size=a[lson].size+a[rson].size+1; a[rt].sum=a[lson].sum+a[rson].sum+a[rt].val; a[rt].maxx=max(a[rt].maxx,max(a[lson].maxx,a[rson].maxx)); a[rt].maxy=max(a[rt].maxy,max(a[lson].maxy,a[rson].maxy)); a[rt].minx=min(a[rt].minx,min(a[lson].minx,a[rson].minx)); a[rt].miny=min(a[rt].miny,min(a[lson].miny,a[rson].miny)); } void buildtree(int l,int r,int &rt,int flag){ int mid=l+r>>1; sort_flag=flag; nth_element(point+l,point+mid,point+r+1); rt=newnode(point[mid]); if(l<mid)buildtree(l,mid-1,a[rt].lson,flag^1); if(mid<r)buildtree(mid+1,r,a[rt].rson,flag^1); pushup(rt); } void pia(int rt,int num){ if(a[rt].lson)pia(a[rt].lson,num); point[num+a[a[rt].lson].size+1]=a[rt].point; recycle[++top]=rt; if(a[rt].rson)pia(a[rt].rson,num+a[a[rt].lson].size+1); } inline void check(int &rt,int flag){ if(Alpha*a[rt].size<max(a[a[rt].lson].size,a[a[rt].rson].size)){ pia(rt,0); buildtree(1,a[rt].size,rt,flag); } } void insert(int &rt,int flag){ if(!rt){ rt=newnode(now); return; } sort_flag=flag; if(a[rt].point<now)insert(a[rt].rson,flag^1); else insert(a[rt].lson,flag^1); pushup(rt); check(rt,flag); } int query(int rt){ if(check_inside(a[rt].minx,a[rt].miny,a[rt].maxx,a[rt].maxy))return a[rt].sum; if(check_outside(a[rt].minx,a[rt].miny,a[rt].maxx,a[rt].maxy))return 0; int ans=0; if(check_inside(a[rt].point.x,a[rt].point.y,a[rt].point.x,a[rt].point.y))ans+=a[rt].val; if(a[rt].lson)ans+=query(a[rt].lson); if(a[rt].rson)ans+=query(a[rt].rson); return ans; } void work(){ int f,last=0; while(1){ f=read(); if(f==3)return; if(f==1){ now.x=read()^last;now.y=read()^last;now.z=read()^last; insert(root,0); } else{ l1=read()^last;r1=read()^last;l2=read()^last;r2=read()^last; last=query(root); printf("%d ",last); } } } void init(){ n=read(); a[0].maxx=a[0].maxy=-MAX; a[0].minx=a[0].miny=MAX; } int main(){ init(); work(); return 0; }