BZOJ#2683. 简单题
2683: 简单题
Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 2091 Solved: 847
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。
题目大意:
给了一个矩形,有查询去其中某个矩形权值之和和修改某个位置的值的操作。
分析:
CDQ裸题
我们可以很方便求出一个前缀面积,就是(0,0)(x,y)的面积,我们只需要按时间排序,在里面再按x排序,y加入树状数组
找到time>time[i],x>=x[i],y>=y[i]即可
那么我们怎么求(x,y)(c,d)的矩形呢?
我们可以把它拆成4个矩形(0,0)(x-1,y-1),(0,0)(x-1,d),(0,0)(c,d),(0,0)(c,y-1)
合并一下就可以了
附上代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//CDQ把每个查询矩形划分为4部分 每部分可以单独求出 //求出的方法是找到x1<x2,y1<y2,时间在他出现之前 //合并答案 #include<bits/stdc++.h> using namespace std; const int N=5e5+12; const int M=8e5+12; struct date { int type,x,y,v,id; }d[M]; int n,m,cnt,c[N],pos[M],ans[M]; int cmp(date a,date b) { return a.x<b.x; } inline int lowbit(int x) {return x&(-x);} void add(int a,int b) { while(a<=n) { c[a]+=b; a+=lowbit(a); } } int sum(int a) { int s=0; while(a) { s+=c[a]; a-=lowbit(a); } return s; } void CDQ(int l,int r) { if(l==r) return ; int mid=(l+r)>>1,temp=0; CDQ(l,mid);CDQ(mid+1,r); sort(d+l,d+mid+1,cmp);sort(d+mid+1,d+r+1,cmp); int i=l,j=mid+1; while(j<=r) { while(d[i].type==2&&i<=mid) i++; while(d[j].type==1&&j<=r) j++; if(i<=mid&&d[i].x<=d[j].x) add(d[i].y,d[i].v),i++,temp=i-1; else if(j<=r) ans[d[j].id]+=sum(d[j].y),j++; } for(int i=l;i<=temp;i++) if(d[i].type==1) add(d[i].y,-d[i].v); } int main() { freopen("a.in","r",stdin); int type,x1,x2,y1,y2; scanf("%d",&n); while(1) { scanf("%d",&type); if(type==3) break; if(type==1) { d[++m].type=type;d[m].id=m; scanf("%d%d%d",&d[m].x,&d[m].y,&d[m].v); } else { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); pos[++cnt]=m; d[++m].type=type;d[m].x=x1-1;d[m].y=y1-1;d[m].id=m; d[++m].type=type;d[m].x=x2;d[m].y=y2;d[m].id=m; d[++m].type=type;d[m].x=x1-1;d[m].y=y2;d[m].id=m; d[++m].type=type;d[m].x=x2;d[m].y=y1-1;d[m].id=m; } } CDQ(1,m); for(int i=1;i<=cnt;i++) printf("%d\n",ans[pos[i]+1]+ans[pos[i]+2]-ans[pos[i]+3]-ans[pos[i]+4]); return 0; }