zoukankan      html  css  js  c++  java
  • 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]);
    }
  • 相关阅读:
    linux
    linux
    linux
    linux
    linux
    linux
    linux
    idea插件篇之java内存分析工具(JProfiler)
    Jmeter(线程组+http请求+汇总报告)
    ZK客户端zkClient.bat
  • 原文地址:https://www.cnblogs.com/MikuKnight/p/9046263.html
Copyright © 2011-2022 走看看