bzoj1935
不建议用cdq,内存达到了159024kb,时间4468ms
这题cdq的想法是:对于两个点(x,y)和(u,v)组成的矩形,我们可以想象成矩形(1,1 u,v)中的所有点减去矩形(1,1 u,y-1)和矩形(1,1 x-1,v)的点,再加上(1,1 x-1,y-1)里的点
x是时间变量,天然有序。y和w(操作种类)分别是每一个点的横坐标和纵坐标
#include<cstdio> #include<cctype> #include<algorithm> #define maxn 500005 #define maxm 10000005 using namespace std; int n,m,cnt,dfn,knum,ans[maxn],sum[maxm],tim[maxm]; struct data{int x,y,id,w;}f[maxn+(maxn<<2)],tmp[maxn+(maxn<<2)]; int read(){ char ch=getchar();int x=0; while(!isdigit(ch))ch=getchar(); while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x; } bool check(data a,data b){ return a.x==b.x?abs(a.w)<abs(b.w):a.x<b.x; } void add(int x,int ad){ for(;x<=knum;){ if(tim[x]!=dfn)tim[x]=dfn,sum[x]=0; sum[x]+=ad; x+=x&-x; } } int getsum(int x){ int res=0; for(;x;){ if(tim[x]==dfn)res+=sum[x];x-=x&-x; } return res; } void cdq(int l,int r){ if(l==r)return; int mid=(l+r)>>1,ii=l,jj=mid+1,st=l-1; cdq(l,mid);cdq(mid+1,r); dfn++; while(ii<=mid && jj<=r){ if(check(f[ii],f[jj])){ if(f[ii].w==0)add(f[ii].y,1); tmp[++st]=f[ii++]; } else{ if(f[jj].w)ans[f[jj].id]+=f[jj].w*getsum(f[jj].y); tmp[++st]=f[jj++]; } } while(ii<=mid)tmp[++st]=f[ii++]; while(jj<=r){ if(f[jj].w)ans[f[jj].id]+=f[jj].w*getsum(f[jj].y); tmp[++st]=f[jj++]; } for(int i=l;i<=r;i++)f[i]=tmp[i]; } int main(){ n=cnt=read();m=read(); for(int i=1;i<=n;i++){ f[i]=(data){read()+1,read()+1,0,0};knum=max(knum,f[i].y); } for(int i=1;i<=m;i++){ int x=read(),y=read(),u=read(),v=read(); f[++cnt]=(data){x,y,i,1};f[++cnt]=(data){x,v+1,i,-1}; f[++cnt]=(data){u+1,y,i,-1};f[++cnt]=(data){u+1,v+1,i,1}; knum=max(knum,y+1);knum=max(knum,v+1); } cdq(1,cnt); for(int i=1;i<=m;i++)printf("%d\n",ans[i]); }
离线树状数组维护的话65280kb 4264ms
按照x坐标排序
再离散化,减小常数(离散y坐标),树状数组维护一下就可以了
#include<cstdio> #include<cctype> #include<cmath> #include<algorithm> #define maxn 500002 #define maxq 2000002 using namespace std; int n,m,tot,cnt,ans[maxn],x[maxn],y[maxn],a[maxn],b[maxn],c[maxn],d[maxn],p[maxq+maxn],tr[maxn]; struct data{int x,y,id,typ;}q[maxq+maxn]; int read(){ char ch=getchar();int x=0; while(!isdigit(ch))ch=getchar(); while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x; } bool cmp(data a,data b){ return a.x<b.x||(a.x==b.x&&abs(a.typ)<abs(b.typ)); } void add(int x,int ad){ for(;x<=n;x+=x&-x)tr[x]+=ad; } int query(int x){ int res=0; for(;x;x-=x&-x)res+=tr[x]; return res; } int main(){ n=read();m=read(); for(int i=1;i<=n;i++){ x[i]=read()+1;y[i]=read()+1;p[++tot]=y[i]; } for(int i=1;i<=m;i++){ a[i]=read()+1;b[i]=read()+1;c[i]=read()+1;d[i]=read()+1; p[++tot]=b[i];p[++tot]=d[i]; } sort(p+1,p+tot+1); tot=unique(p+1,p+tot+1)-p-1; for(int i=1;i<=n;i++){ y[i]=lower_bound(p+1,p+tot+1,y[i])-p; q[++cnt].x=x[i];q[cnt].y=y[i]; } for(int i=1;i<=m;i++){ b[i]=lower_bound(p+1,p+tot+1,b[i])-p; d[i]=lower_bound(p+1,p+tot+1,d[i])-p; q[++cnt]=(data){a[i]-1,b[i]-1,i,1}; q[++cnt]=(data){a[i]-1,d[i],i,-1}; q[++cnt]=(data){c[i],b[i]-1,i,-1}; q[++cnt]=(data){c[i],d[i],i,1}; } sort(q+1,q+cnt+1,cmp); for(int i=1;i<=cnt;i++){ if(!q[i].typ)add(q[i].y,1);else ans[q[i].id]+=q[i].typ*query(q[i].y); } for(int i=1;i<=m;i++)printf("%d\n",ans[i]); }