洛谷 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\n",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",n,m,q);
    while(q--)
    {
        x=rand()%n+1; y=rand()%m+1;
        printf("%d %d\n",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\n",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\n",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\n",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\n",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\n",d.val);
            del(rt[0],1,lm,d.pos);
            ++dr[0];insert(rt[0],1,lm,dr[0],d.val);
        }
    }
    return 0;
}

 

posted on 2018-09-10 16:28  Narh  阅读(276)  评论(0编辑  收藏  举报

导航