Luogu3960 NOIP2017列队(splay)

  令splay中的一个点表示一段区间,需要使用其中某个点时将区间分裂即可,剩下的都是splay的基本操作了。写的非常丑陋,注意细节。感觉考场上肯定只能靠部分分苟活了。想起来去年因为各种莫名其妙的原因50->0

  线段树做法待补。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 300010
#define lson tree[k].ch[0]
#define rson tree[k].ch[1]
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,q,row[N],line,cnt;
struct data{int ch[2],fa,len,size;ll id;
}tree[N<<4];
ll trans(int x,int y){return 1ll*(x-1)*m+y;}
void up(int k){tree[k].size=tree[lson].size+tree[rson].size+tree[k].len;}
int whichson(int k){return tree[tree[k].fa].ch[1]==k;}
void move(int k)
{
    int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k);
    tree[gf].ch[whichson(fa)]=k,tree[k].fa=gf;
    tree[tree[k].ch[!p]].fa=fa,tree[fa].ch[p]=tree[k].ch[!p];
    tree[k].ch[!p]=fa,tree[fa].fa=k;
    up(fa),up(k);
}
void splay(int k,int rt,int &root)
{
    while (tree[k].fa!=rt)
    {
        int fa=tree[k].fa;
        if (tree[fa].fa!=rt)
            if (whichson(fa)^whichson(k)) move(k);
            else move(fa);
        move(k);
    }
    if (!rt) root=k;
}
int find(int k,int x)
{
    if (tree[lson].size<x&&tree[lson].size+tree[k].len>=x) return k;
    else if (tree[lson].size>=x) return find(lson,x);
    else return find(rson,x-tree[lson].size-tree[k].len);
}
int getid(int k,int x)
{
    if (tree[lson].size<x&&tree[lson].size+tree[k].len>=x) return x-tree[lson].size;
    else if (tree[lson].size>=x) return getid(lson,x);
    else return getid(rson,x-tree[lson].size-tree[k].len);
}
int nxt(int k){if (!lson) return k;return nxt(lson);}
void ins(int &k,int l,int r,ll id)
{
    cnt++;tree[cnt].size=tree[cnt].len=r-l+1,tree[cnt].id=id;
    int p=find(k,l);splay(p,0,k);
    int q=nxt(tree[p].ch[1]);splay(q,p,k);
    tree[q].ch[0]=cnt;tree[cnt].fa=q;up(q);up(p);
}
void del(int &k,int l,int r)
{
    int p=find(k,l),q=find(k,r+2);
    splay(p,0,k);splay(q,p,k);
    tree[q].ch[0]=0;up(q);up(p);
}
ll split(int x,int y)
{
    int k=find(row[x],y+1),p=getid(row[x],y+1);
    del(row[x],y-p+1,y+tree[k].len-p);
    if (p>1) ins(row[x],y-p+1,y-1,tree[k].id);
    if (p<tree[k].len) ins(row[x],y,y+tree[k].len-p-1,tree[k].id+p);
    return tree[k].id+p-1;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("phalanx.in","r",stdin);
    freopen("phalanx.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read(),m=read(),q=read();
    for (int i=1;i<=n;i++)
    {
        row[i]=++cnt;tree[cnt].len=m-1,tree[cnt].size=m+1;tree[cnt].id=trans(i,1);
        cnt++;tree[cnt].len=tree[cnt].size=1;tree[cnt].fa=row[i],tree[row[i]].ch[0]=cnt;
        cnt++;tree[cnt].len=tree[cnt].size=1;tree[cnt].fa=row[i],tree[row[i]].ch[1]=cnt;
    }
    line=++cnt;tree[cnt].len=1,tree[cnt].size=2;
    cnt++;tree[cnt].len=tree[cnt].size=1;tree[cnt].fa=line,tree[line].ch[1]=cnt;
    for (int i=1;i<=n;i++) ins(line,i,i,trans(i,m));
    while (q--)
    {
        int x=read(),y=read();
        ll id;
        if (y<m)
        {
            id=split(x,y);
            int k=find(line,x+1);
            del(line,x,x);
            ins(row[x],m-1,m-1,tree[k].id);
        }
        else
        {
            int k=find(line,x+1);
            del(line,x,x);
            id=tree[k].id;
        }
        ins(line,n,n,id);
        printf(LL,id);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Gloid/p/9932895.html
今日推荐