洛谷P3960 列队(Splay)

传送门

 

感觉自己好久不打数据结构已经完全不会了orz……

据说正解树状数组?然而并不会

首先考虑一下每一次操作,就是把一个人从这一行中取出并放到行的最后,再从最后一列取出放到列的最后

那么这两种操作其实可以看做同一个类型,都是把某一个数取出并放到最后

那么这个可以用splay来搞,用splay维护区间,然后每一次找第k个相当于找第k大,然后删除之后在末尾插入

然后如果直接开空间怕是要炸……那只能缩点,等做到这个点的时候再把它split出来……

然后……看代码好了……

  1 //minamoto
  2 #include<cstdio>
  3 #include<iostream>
  4 #define ll long long
  5 #define inf 0x3f3f3f3f
  6 using namespace std;
  7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
  8 char buf[1<<21],*p1=buf,*p2=buf;
  9 inline int read(){
 10     #define num ch-'0'
 11     char ch;bool flag=0;int res;
 12     while(!isdigit(ch=getc()))
 13     (ch=='-')&&(flag=true);
 14     for(res=num;isdigit(ch=getc());res=res*10+num);
 15     (flag)&&(res=-res);
 16     #undef num
 17     return res;
 18 }
 19 char sr[1<<21],z[20];int C=-1,Z;
 20 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
 21 inline void print(ll x){
 22     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
 23     while(z[++Z]=x%10+48,x/=10);
 24     while(sr[++C]=z[Z],--Z);sr[++C]='\n';
 25 }
 26 const int N=1e7+5,maxn=3e5+5;
 27 int n,m,q,x,y;ll t,u;
 28 int fa[N],ch[N][2],tot;ll L[N],R[N],sz[N];
 29 struct Splay{
 30     #define ls ch[x][0]
 31     #define rs ch[x][1]
 32     int rt;
 33     inline int newnode(ll l,ll r){
 34         L[++tot]=l,R[tot]=r,sz[tot]=r-l+1;return tot;
 35     }
 36     inline void upd(int x){
 37         sz[x]=sz[ls]+sz[rs]+R[x]-L[x]+1;
 38     }
 39     void rotate(int x){
 40         int y=fa[x],z=fa[y],d=ch[y][1]==x;
 41         ch[z][ch[z][1]==y]=x;
 42         fa[x]=z,fa[y]=x,fa[ch[x][d^1]]=y,ch[y][d]=ch[x][d^1],ch[x][d^1]=y,upd(y);
 43     }
 44     void splay(int x){
 45         for(int y=fa[x],z=fa[y];fa[x];y=fa[x],z=fa[y]){
 46             if(fa[y])
 47             ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y);
 48             rotate(x);
 49         }
 50         upd(x),rt=x;
 51     }
 52     inline void ins(ll v){
 53         int x=rt;
 54         while(rs) x=rs;
 55         newnode(v,v),fa[tot]=x,rs=tot,splay(tot);
 56     }
 57     ll split(int x,ll k){
 58         ll s=L[x],t=R[x];
 59         if(k!=s&&k!=t){
 60             if(s+1<t){
 61                 int a=newnode(k+1,t);R[x]=k-1;
 62                 ch[a][1]=ch[x][1],ch[x][1]=a,fa[a]=x,upd(a),upd(x);
 63                 splay(a);
 64             }else{++L[x],splay(x);}
 65         }else{
 66             k==t?--t:++s;
 67             L[x]=s,R[x]=t,sz[x]=t-s+1,splay(x); 
 68         }
 69         return k;
 70     }
 71     ll rk(int k){
 72         int x=rt;
 73         while(true){
 74             if(sz[ls]>=k) x=ls;
 75             else{
 76                 k-=sz[ls];
 77                 if(k<=R[x]-L[x]+1) return split(x,k+L[x]-1);
 78                 k-=R[x]-L[x]+1,x=rs;
 79             }
 80         }
 81     }
 82     inline void init(ll l,ll r){rt=newnode(l,r);}
 83     int build(int l,int r,int f){
 84         if(l>r) return 0;
 85         int mid=(l+r)>>1,x=newnode(1ll*m*mid,1ll*m*mid);
 86         fa[x]=f;
 87         ls=build(l,mid-1,x);
 88         rs=build(mid+1,r,x);
 89         return upd(x),x;
 90     }
 91 }T[maxn];
 92 int main(){
 93 //    freopen("testdata.in","r",stdin);
 94     n=read(),m=read(),q=read();
 95     for(int i=1;i<=n;++i) T[i].init(1ll*(i-1)*m+1,1ll*i*m-1);
 96     T[0].rt=T[0].build(1,n,0);
 97     while(q--){
 98         x=read(),y=read();
 99         if(y==m){
100             print(u=T[0].rk(x)),T[0].ins(u);
101         }else{
102             print(u=T[x].rk(y));
103             t=T[0].rk(x);
104             T[x].ins(t),T[0].ins(u);
105         }
106     }
107     Ot();
108     return 0;
109 }

 

posted @ 2018-09-27 16:07  bztMinamoto  阅读(177)  评论(0编辑  收藏  举报
Live2D