题目描述
C 国国土辽阔,地大物博,但是最近却在闹蝗灾……
我们可以把 C 国国土当成一个 W×WW×W 的矩阵,你会收到一些诸如 (X,Y,Z)(X,Y,Z) 的信息,代表 (X,Y)(X,Y) 这个点增多了 ZZ 只蝗虫,而由于 C 国政府机关比较臃肿,为了批复消灭蝗虫的请求需要询问一大堆的问题,每个询问形如 (X1,Y1,X2,Y2)(X1,Y1,X2,Y2),询问在 (X1,Y1,X2,Y2)(X1,Y1,X2,Y2) 范围内有多少蝗虫(请注意询问不会改变区域内的蝗虫数)。
你作为一个 C 国的程序员,需要编一个程序快速的回答所有的询问。
注意:C 国一开始没有蝗虫。
输入
输入的第一行包括一个整数 WW,代表 C 国国土的大小;
第二行有一个整数 NN,表示事件数;
接下来有 NN 行表示 NN 个事件,以 1 X Y Z 的形式或 2 X1X1 Y1Y1 X2X2 Y2Y2 的形式给出,分别代表蝗虫的增加和询问。
输出
对于每个询问输出一个整数表示需要的结果。
样例输入
5
8
2 4 1 4 2
1 3 1 8
1 4 4 4
2 1 3 4 4
1 1 5 1
1 4 4 5
2 2 2 5 4
2 3 2 4 4
样例输出
0
4
9
9
提示
10%10% 的数据满足 W,N≤100W,N≤100;
30%30% 的数据满足 W≤2×103,N≤5×103W≤2×103,N≤5×103;
50%50% 的数据满足 W≤105,N≤5×104W≤105,N≤5×104;
100%100% 的数据满足 W≤5×105,N≤2×105W≤5×105,N≤2×105,每次蝗虫增加数不超过 103103。
啊我太弱了,还要看题解。。。多练练cdq分治233
所以说,cdq的核心思想就是分块,拆开,这样就只需要考虑合并问题时多出来需要考虑的问题就好了,而这些问题往往都比原问题简单
这道题首先把操作和询问按时间顺序放在一起
这样从中间分开的话,多出来的问题就是,左边的修改对右边的询问造成的影响
因为首先合并的时候左边询问不受任何影响是显然的吧?之后的修改影响不了询问
而右边的询问既需要右边的一些修改,也会需要左边的修改
而这样的话就发现修改与询问之间的先后顺序被解决了
用扫描线的方式按x排序用树状数组处理
x从小到大扫过去
对于一个修改,就在这个y位置上加z
遇到一个矩形左边,就在答案上减去这个区间的和
遇到一个矩形右边,就在答案上加上这个区间的和
具体细节看代码吧~(ง •_•)ง
1 #include<cstdio> 2 #include<algorithm> 3 #define maxn 200005 4 #define maxw 500005 5 using namespace std; 6 int w,n,cnt; 7 struct event{ 8 int opt,x1,y1,x2,y2,z,id; 9 }A[maxn],B[maxn]; 10 bool cmp(event A,event B){return (A.x1!=B.x1)?(A.x1<B.x1):(A.opt<B.opt);} 11 int ans[maxn],c[maxw]; 12 void add(int x,int z){while(x<=w+1){c[x]+=z;x+=(x&(-x));}} 13 int sum(int x){int ans=0;while(x>=1){ans+=c[x];x-=(x&(-x));}return ans;} 14 int query(int l,int r){return sum(r)-sum(l-1);} 15 void solve(int l,int r){ 16 if(l==r)return; 17 int mid=(l+r)/2; 18 solve(l,mid);solve(mid+1,r); 19 int d=0; 20 for(int i=l;i<=mid;i++) 21 if(A[i].opt==1) 22 B[d++]=A[i]; 23 for(int i=mid+1;i<=r;i++) 24 if(A[i].opt==2){ 25 B[d]=A[i];B[d].x1--;d++; 26 B[d]=A[i];B[d].opt=3;B[d].x1=B[d].x2;d++; 27 } 28 sort(B,B+d,cmp); 29 for(int i=0;i<d;i++){ 30 if(B[i].opt==1)add(B[i].y1,B[i].z); 31 else if(B[i].opt==2)ans[B[i].id]-=query(B[i].y1,B[i].y2); 32 else ans[B[i].id]+=query(B[i].y1,B[i].y2); 33 } 34 for(int i=0;i<d;i++)if(B[i].opt==1)add(B[i].y1,-B[i].z); 35 } 36 int main(){ 37 scanf("%d%d",&w,&n); 38 for(int i=1;i<=n;i++){ 39 scanf("%d%d%d",&A[i].opt,&A[i].x1,&A[i].y1);A[i].y1++; 40 if(A[i].opt==1)scanf("%d",&A[i].z); 41 else scanf("%d%d",&A[i].x2,&A[i].y2),A[i].y2++; 42 A[i].id=i; 43 } 44 solve(1,n); 45 for(int i=1;i<=n;i++) 46 if(A[i].opt==2) 47 printf("%d ",ans[A[i].id]); 48 return 0; 49 }