COGS 577 蝗灾

题目描述

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 的形式或 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,N100W,N≤100;

30%30% 的数据满足 W2×103,N5×103W≤2×103,N≤5×103;

50%50% 的数据满足 W105,N5×104W≤105,N≤5×104;

100%100% 的数据满足 W5×105,N2×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\n",ans[A[i].id]);
48     return 0;
49 }
View Code

猜你喜欢

转载自www.cnblogs.com/2017SSY/p/10198821.html