这题本来是想用二维树状数组水的。然后不会动态开数组,所以顺便补了一发cdq。
第一维时间,第二维x,第三维y,(其实我自己的感觉是第一维可以不要的),xy很大so离散化谢谢。
询问拆成4个。大家都懂。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int n,m; struct node { int x,y,tp; }c[4100000];int clen; void ins(int x,int y,int tp) { clen++; c[clen].x=x;c[clen].y=y;c[clen].tp=tp; } int ls[8100000],lslen; void LSH() { lslen=0; for(int i=1;i<=clen;i++) { ls[++lslen]=c[i].x; ls[++lslen]=c[i].y; } sort(ls+1,ls+lslen+1); lslen=unique(ls+1,ls+1+lslen)-ls-1; for(int i=1;i<=clen;i++) { c[i].x=lower_bound(ls+1,ls+lslen+1,c[i].x)-ls; c[i].y=lower_bound(ls+1,ls+lslen+1,c[i].y)-ls; } } int s[4100000]; int lowbit(int x){return x&-x;} void change(int x,int k) { while(x<=lslen) { s[x]+=k; x+=lowbit(x); } } int getsum(int x) { int ret=0; while(x>=1) { ret+=s[x]; x-=lowbit(x); } return ret; } int as[510000]; node tt[4100000]; void cdq(int l,int r) { if(l==r)return ; int mid=(l+r)/2; cdq(l,mid);cdq(mid+1,r); int i=l,j=mid+1,p=l; while(i<=mid&&j<=r) { if(c[i].x<c[j].x||(c[i].x==c[j].x&&abs(c[i].tp)<abs(c[j].tp))) { if(c[i].tp==0)change(c[i].y,1); tt[p++]=c[i++]; } else { if(c[j].tp!=0) { if(c[j].tp>0)as[c[j].tp]+=getsum(c[j].y); else as[-c[j].tp]-=getsum(c[j].y); } tt[p++]=c[j++]; } } while(i<=mid) { if(c[i].tp==0)change(c[i].y,1); tt[p++]=c[i++]; } while(j<=r) { if(c[j].tp!=0) { if(c[j].tp>0)as[c[j].tp]+=getsum(c[j].y); else as[-c[j].tp]-=getsum(c[j].y); } tt[p++]=c[j++]; } for(int i=l;i<=mid;i++) if(c[i].tp==0)change(c[i].y,-1); for(int i=l;i<=r;i++)c[i]=tt[i]; } int main() { scanf("%d%d",&n,&m); int x,y;clen=0; for(int i=1;i<=n;i++) scanf("%d%d",&x,&y), ins(x+1,y+1,0); int sx,sy,bx,by; for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&sx,&sy,&bx,&by); sx++;sy++;bx++;by++; ins(bx,by,i); ins(sx-1,by,-i); ins(bx,sy-1,-i); ins(sx-1,sy-1,i); } LSH(); cdq(1,clen); for(int i=1;i<=m;i++)printf("%d ",as[i]); return 0; }