bzoj1935 Tree 园丁的烦恼(二位偏序,CDQ分治+树状数组)

传送:https://www.lydsy.com/JudgeOnline/problem.php?id=1935

题意:有$n$个点,$m$个询问,每次询问为一个矩形,问矩形内有多少个点。

数据范围:$0 \le n \le 500000$,$0 \le m \le 500000$,$0 \le x_i,y_i \le 10000000$

分析:

每次都是询问一个矩形内点的个数。可以按照一维排序,另一维用树状数组维护。

同样,这个题可以转化为二维偏序去做。CDQ分治。

维护x维有序,另一维用树状数组维护。

对于每个矩形$x_1,y_1,x_2,y_2$,答案就是$ans(x_2,y_2)-ans(x_1-1,y_2)-ans(x_2,y_1-2)+ans(x_1-1,y_1-1)$。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=5e5+10;
 4 const int maxm=1e7+10;
 5 struct node{
 6     int x,y,type,id;
 7 }a[maxn*5],b[maxn*5];
 8 int tree[maxm],ans[maxn];
 9 int mx,cnt;
10 int lowbit(int x){
11     return x&-x;
12 }
13 void add(int x,int val){
14     while (x<=mx){
15         tree[x]+=val;
16         x+=lowbit(x);
17     }
18 } 
19 int query(int x){
20     int res=0;
21     while (x>0){
22         res+=tree[x];
23         x-=lowbit(x);
24     }
25     return res;
26 }
27 void _clear(int x){
28     while (x<=mx){
29         if (tree[x]==0) break;
30         tree[x]=0;
31         x+=lowbit(x);
32     }
33 }
34 void cdq(int l,int r){
35     if (l==r) return ;
36     int mid=(l+r)>>1;
37     cdq(l,mid);
38     cdq(mid+1,r);
39     int i=l,j=mid+1,kk=l;
40     while (i<=mid && j<=r){
41         if(a[i].x<=a[j].x){
42             if (a[i].type==1) add(a[i].y,1);
43             b[kk++]=a[i++];    
44         }
45         else{
46             if (a[j].type==2) ans[a[j].id]+=query(a[j].y);
47             else if (a[j].type==3) ans[a[j].id]-=query(a[j].y);
48             b[kk++]=a[j++]; 
49         }
50     }
51     while (i<=mid){
52         if (a[i].type==1) add(a[i].y,1);
53         b[kk++]=a[i++];    
54     }
55     while (j<=r){
56         if (a[j].type==2) ans[a[j].id]+=query(a[j].y);
57         else if (a[j].type==3) ans[a[j].id]-=query(a[j].y);
58         b[kk++]=a[j++]; 
59     }
60     for (int i=l;i<=r;i++){
61         _clear(a[i].y); a[i]=b[i];
62     }
63 }
64 int main(){
65     int n,m,sx,sy,ex,ey;
66     scanf("%d%d",&n,&m);
67     cnt=0; mx=0;
68     for (int i=1;i<=n;i++){
69         cnt++;
70         scanf("%d%d",&a[cnt].x,&a[cnt].y);
71         a[cnt].x++;a[cnt].y++;
72         a[cnt].id=i; a[cnt].type=1;
73         mx=max(mx,a[cnt].y);
74     }
75     for (int i=1;i<=m;i++){
76         scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
77         sx++; sy++; ex++; ey++;
78         a[++cnt]={sx-1,sy-1,2,i};
79         a[++cnt]={ex,ey,2,i};
80         a[++cnt]={sx-1,ey,3,i};
81         a[++cnt]={ex,sy-1,3,i};
82         mx=max(mx,sy);mx=max(mx,ey);
83         ans[i]=0;
84     }
85     cdq(1,cnt);
86     for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
87     return 0;
88 }

 

posted @ 2019-07-13 14:56  Changer-qyz  阅读(157)  评论(0编辑  收藏  举报