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 }