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]);
}
posted @ 2018-05-16 15:32  lnyzo  阅读(184)  评论(0编辑  收藏  举报