BZOJ 2683 简单题
2683: 简单题
Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 1798 Solved: 729
[Submit][Status][Discuss]
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。
接下来每行一个操作。
Output
对于每个2操作,输出一个对应的答案。
Sample Input
4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
Sample Output
3
5
5
HINT
1<=N<=500000,操作数不超过200000个,内存限制20M。
对于100%的数据,操作1中的A不超过2000。
Source
裸的CDQ分治
#include <bits/stdc++.h> #define inf 10000000 #define ll long long using namespace std; inline int read(){ int x=0;int f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const int MAXN=1e6+10; struct node{ int x1,y1,x2,y2; int x,y,v; int op,id; }a[MAXN],b[MAXN],d[MAXN]; int ans[MAXN],c[MAXN],n,m; inline int lowbit(int x) {return x&-x;} inline void add(int x,int vv){ while(x<=MAXN){ c[x]+=vv; x+=lowbit(x); } } inline int get(int x){ int ans=0; while(x){ ans+=c[x]; x-=lowbit(x); } return ans; } inline bool cmp1(node n,node m){ return n.x1<m.x1; } inline bool cmp2(node n,node m){ return n.x2<m.x2; } inline bool cmp3(node n,node m){ return n.x<m.x; } void CDQ(int l,int r){ if(l!=r){ int mid=(r+l)>>1; CDQ(l,mid);CDQ(mid+1,r); int p=0; for(int i=l;i<=mid;i++){ if(a[i].op==1){ b[++p]=a[i]; } } sort(b+1,b+p+1,cmp3); int p1=0; for(int i=mid+1;i<=r;i++){ if(a[i].op==2){ d[++p1]=a[i]; } } sort(d+1,d+p1+1,cmp1); int i1=1,i2=1; while(i1<=p&&i2<=p1){ if(b[i1].x<=d[i2].x1-1){ add(b[i1].y,b[i1].v); i1++; } else{ ans[d[i2].id]-=get(d[i2].y2)-get(d[i2].y1-1); i2++; } } for(int i=i2;i<=p1;i++){ ans[d[i].id]-=get(d[i].y2)-get(d[i].y1-1); } for(int i=1;i<=i1-1;i++){ add(b[i].y,-b[i].v); } sort(d+1,d+p1+1,cmp2); i1=1,i2=1; while(i1<=p&&i2<=p1){ if(b[i1].x<=d[i2].x2){ add(b[i1].y,b[i1].v); i1++; } else{ ans[d[i2].id]+=get(d[i2].y2)-get(d[i2].y1-1); i2++; } } for(int i=i2;i<=p1;i++){ ans[d[i].id]+=get(d[i].y2)-get(d[i].y1-1); } for(int i=1;i<=i1-1;i++){ add(b[i].y,-b[i].v); } } } int main(){ n=read(); a[++m].op=read(); while(a[m].op!=3){ a[m].id=m; if(a[m].op==1) a[m].x=read(),a[m].y=read(),a[m].v=read(); else a[m].x1=read(),a[m].y1=read(),a[m].x2=read(),a[m].y2=read(); a[++m].op=read(); } CDQ(1,m-1); for(int i=1;i<=m;i++){ if(a[i].op==2) printf("%d\n",ans[i]); } return 0; }