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 的形式给出,分别代表蝗虫的增加和询问。
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\n",ans[A[i].id]);
48 return 0;
49 }
View Code