zoukankan      html  css  js  c++  java
  • 洛谷 3960 列队——线段树

    题目:https://www.luogu.org/problemnew/show/P3960

    用了朴素的方法调了众多细节之后以一个很慢的速度A了……

    大意是给每行开一个线段树,存1~m-1的点,最后一列开一个线段树。一开始有n*m个点开不下,但是顺序的,所以打一个标记表示它是顺序的,就不用建出它的孩子了。这样初始开了大约nlogn个节点。

    线段树节点上记录 sm[ ] 表示该段内有多少个值。查询 y 位置就是查询第 x 行的线段树里第 y 靠前的值。

    新加一个值就直接加到后面,不要把前面的都挪一下什么的。这样空间有点紧张。不过一次询问最多增加 2*log( max(n,m) + q ) 个点。512MB可以开3e5*80个线段树节点。

    注意开long long!!!!!不仅是定义里和函数参数里,主函数里还有一处!!!

    先放一下对拍程序:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=5005;
    int n,m,q,a[N][N],tot;
    int rdn()
    {
        int ret=0;char ch=getchar();
        while(ch>'9'||ch<'0') ch=getchar();
        while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
        return ret;
    }
    int main()
    {
        n=rdn(); m=rdn(); q=rdn();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++) a[i][j]=++tot;
        for(int i=1,d,x,y;i<=q;i++)
        {
            x=rdn(); y=rdn(); d=a[x][y];
            printf("%d
    ",d);
            for(int j=y;j<m;j++) a[x][j]=a[x][j+1];
            for(int j=x;j<n;j++) a[j][m]=a[j+1][m];
            a[n][m]=d;
        }
        return 0;
    }
    暴力
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<ctime>
    using namespace std;
    const int mod=300001;
    int n,m,q,x,y;
    int main()
    {
        srand(time(0));
        n=rand()%mod+1; m=rand()%mod+1; q=rand()%mod+1;
    //    n=mod-1; m=mod-1; q=mod-1;
        printf("%d %d %d
    ",n,m,q);
        while(q--)
        {
            x=rand()%n+1; y=rand()%m+1;
            printf("%d %d
    ",x,y);
        }
        return 0;
    }
    maker
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int main()
    {
        int cnt=0;
        while(1)
        {
            system(" lg3960-maker.exe > lg3960-data.in ");
            system(" lg3960.exe < lg3960-data.in > lg3960-zj.out ");
            system(" lg3960-baoli.exe < lg3960-data.in > lg3960-bl.out ");
            if(system(" fc lg3960-zj.out lg3960-bl.out ")) return 0;
            cnt++; printf("%d
    ",cnt);
        }
    }
    对拍
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ls Ls[cr]
    #define rs Rs[cr]
    #define ll long long
    using namespace std;
    const int N=3e5+5,M=N*80;
    int n,m,q,lm,rt[N],Ls[M],Rs[M],sm[M],dr[N],cr,tot;
    ll val[M];
    bool tg[M];
    struct Node{ll val;int pos;Node(ll v,int p):val(v),pos(p) {}};
    int rdn()
    {
        int ret=0;char ch=getchar();
        while(ch>'9'||ch<'0') ch=getchar();
        while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
        return ret;
    }
    void pshp(int cr)
    {
        tg[cr]=(tg[ls]&tg[rs]); sm[cr]=sm[ls]+sm[rs];
    }
    void build(int &cr,int l,int r,int L,int R,ll ini)
    {
        if(L>R) return;//仅一列 
        cr=++tot;
        if(l>=L&&r<=R){sm[cr]=r-l+1; tg[cr]=1; val[cr]=ini; return;}
        int mid=l+r>>1;
        if(L<=mid) build(ls,l,mid,L,R,ini);
        if(mid<R) build(rs,mid+1,r,L,R,ini+(mid-l+1));
        pshp(cr);
    }
    void insert(int &cr,int l,int r,int p,ll v)
    {
        if(!cr) cr=++tot; sm[cr]++; tg[cr]=0;
    //    printf("insert l=%d r=%d sm=%d
    ",l,r,sm[cr]);
        if(l==r) {val[cr]=v; return;}
        int mid=l+r>>1;
        if(p<=mid) insert(ls,l,mid,p,v);
        else insert(rs,mid+1,r,p,v);
    }
    Node query(int cr,int l,int r,int k)
    {
    //    printf("l=%d r=%d k=%d sm=%d tg=%d
    ",l,r,k,sm[cr],tg[cr]);
        if(l==r) return Node(val[cr],l);
        if(tg[cr]){return Node(val[cr]+k-1,l+k-1);}
        int mid=l+r>>1;
        if(k<=sm[ls]) return query(ls,l,mid,k);
        else return query(rs,mid+1,r,k-sm[ls]);
    }
    void del(int &cr,int l,int r,int p)
    {
        sm[cr]--; if(l==r) return;
        int mid=l+r>>1;
        if(tg[cr])
        {
            tg[cr]=0;
            if(p<=mid)
            {
                rs=++tot; sm[rs]=r-mid; val[rs]=val[cr]+(mid-l+1); tg[rs]=1;
                ls=++tot; sm[ls]=mid-l+1; val[ls]=val[cr]; tg[ls]=1;
                del(ls,l,mid,p);
            }
            else
            {
                ls=++tot; sm[ls]=mid-l+1; val[ls]=val[cr]; tg[ls]=1;
                rs=++tot; sm[rs]=r-mid; val[rs]=val[cr]+(mid-l+1); tg[rs]=1;
                del(rs,mid+1,r,p);
            }
            return;
        }
        if(p<=mid) del(ls,l,mid,p);
        else del(rs,mid+1,r,p);
    }
    int main()
    {
        n=rdn();m=rdn();q=rdn(); lm=max(n,m)+q;
        for(int i=1;i<=n;i++)
            build(rt[i],1,lm,1,m-1,(ll)(i-1)*m+1),dr[i]=m-1;
        for(ll i=m,j=1;j<=n;j++,i+=m)//ll
            ++dr[0],insert(rt[0],1,lm,dr[0],i);
        for(int i=1,x,y;i<=q;i++)
        {
            x=rdn(); y=rdn();
            if(y!=m)
            {
                Node d=query(rt[x],1,lm,y);
                printf("%lld
    ",d.val); ll tmp=d.val;
                del(rt[x],1,lm,d.pos);
                d=query(rt[0],1,lm,x);
                ++dr[x];insert(rt[x],1,lm,dr[x],d.val);
                del(rt[0],1,lm,d.pos);
                ++dr[0];insert(rt[0],1,lm,dr[0],tmp);
            }
            else
            {
                Node d=query(rt[0],1,lm,x);
                printf("%lld
    ",d.val);
                del(rt[0],1,lm,d.pos);
                ++dr[0];insert(rt[0],1,lm,dr[0],d.val);
            }
        }
        return 0;
    }
  • 相关阅读:
    抓取csdn上的各类别的文章 (制作csdn app 二)
    Android 使用Fragment,ViewPagerIndicator 制作csdn app主要框架
    MongoDB基本使用
    MongoDB之DBref(关联插入,查询,删除) 实例深入
    nginx 1.4.7 发送日志到rsyslog
    nginx 编译参数
    nginx 编译参数
    rsyslog 传输日志
    rsyslog 传输日志
    rsyslog 直接读取日志,当日志截断后,不会继续发送
  • 原文地址:https://www.cnblogs.com/Narh/p/9620624.html
Copyright © 2011-2022 走看看