题解: cdq分治一下即可 把查询分成四个矩形
#include <bits/stdc++.h> const int MAXN=8e5+10; const int NM=5e5+10; using namespace std; const int inf=1e9; typedef struct node{ int x,y,id,vul; }node; node d[MAXN],p[MAXN];int ans[NM]; int sum[NM],n; int get_id(int x){return x&(-x);} void add(int x,int vul){ for(int i=x;i<=n;i+=get_id(i))sum[i]+=vul; } int Sum(int x){ int ans1=0; for(int i=x;i>0;i-=get_id(i))ans1+=sum[i]; return ans1; } void clear(int x){ if(!x)return ; for(int i=x;i<=n;i+=get_id(i))sum[i]=0; } void merge(int l,int mid,int r){ int i=l;int j=mid+1;int cnt=0; //cout<<l<<"++++"<<r<<endl; while(i<=mid&&j<=r){ while(i<=mid&&d[i].x<=d[j].x){ if(!d[i].id)add(d[i].y,d[i].vul); p[++cnt]=d[i];i++; } if(d[j].id>0)ans[d[j].id]+=Sum(d[j].y); if(d[j].id<0)ans[-1*d[j].id]-=Sum(d[j].y); p[++cnt]=d[j];j++; //cout<<l<<":::"<<r<<i<<" "<<j<<endl; } if(j<=r){ for(;j<=r;j++){ if(d[j].id>0)ans[d[j].id]+=Sum(d[j].y); if(d[j].id<0)ans[-1*d[j].id]-=Sum(d[j].y); p[++cnt]=d[j]; } } //cout<<"sb"<<endl; if(i<=mid){ for(;i<=mid;i++)p[++cnt]=d[i]; } //cout<<"sb"<<endl; for(int i=1;i<=cnt;i++)d[l+i-1]=p[i],clear(p[i].y); } void cdq(int l,int r){ //cout<<l<<" "<<r<<endl; if(l>=r)return ; int mid=(l+r)>>1; cdq(l,mid); cdq(mid+1,r); merge(l,mid,r); //cout<<l<<" "<<r<<" "<<mid<<endl; //for(int i=l;i<=r;i++)cout<<d[i].x<<"===="<<d[i].y<<" "<<d[i].id<<endl; } int main(){ scanf("%d",&n); int op,x1,x2,y1,y2;int cnt=0,cnt1=0; for(int i=1;;i++){ scanf("%d",&op); if(op==3)break; cnt1++; if(op==1)scanf("%d%d%d",&x1,&y1,&y2),d[++cnt].x=x1,d[cnt].y=y1,d[cnt].id=0,d[cnt].vul=y2,ans[i]=inf; else{ scanf("%d%d%d%d",&x1,&y1,&x2,&y2);ans[i]=0; d[++cnt].x=x2;d[cnt].y=y2;d[cnt].id=i; d[++cnt].x=x1-1;d[cnt].y=y1-1;d[cnt].id=i; d[++cnt].x=x1-1;d[cnt].y=y2;d[cnt].id=-i; d[++cnt].x=x2;d[cnt].y=y1-1;d[cnt].id=-i; } } cdq(1,cnt); //cout<<cnt1<<endl; for(int i=1;i<=cnt1;i++){ if(ans[i]!=inf)printf("%d ",ans[i]); } return 0; }
2683: 简单题
Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 2225 Solved: 916
[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。