「luogu2596 」[ZJOI2006]书架

Posted Cupcake

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「luogu2596 」[ZJOI2006]书架相关的知识,希望对你有一定的参考价值。

用平衡树维护每本书的位置

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=80010;
  4 int n,m,maxpos,minpos,book[N<<2],bookpos[N];
  5 int root,fa[N<<2],ch[N<<2][2],siz[N<<2],pos[N<<2],id[N<<2],totnode;
  6 inline int read(){
  7     int x=0,w=1;char c=0;
  8     while(c<0||c>9){if(c==-) w=-1;c=getchar();}
  9     while(c>=0&&c<=9) x=x*10+c-48,c=getchar();
 10     return x*w;
 11 }
 12 inline void updata(int k){
 13     siz[k]=1;
 14     if(ch[k][0]) siz[k]+=siz[ch[k][0]];
 15     if(ch[k][1]) siz[k]+=siz[ch[k][1]];
 16     return;
 17 }
 18 int build(int dad,int l,int r){
 19     if(l>r) return 0;
 20     int mid=(l+r)>>1;
 21     int nownode=++totnode;
 22     fa[nownode]=dad,pos[nownode]=mid,id[nownode]=book[mid];
 23     ch[nownode][0]=build(nownode,l,mid-1),ch[nownode][1]=build(nownode,mid+1,r);
 24     updata(nownode);
 25     return nownode;
 26 }
 27 inline bool which(int k){return ch[fa[k]][1]==k;}
 28 inline void rotate(int k){
 29     int old=fa[k],oldf=fa[old],whnow=which(k),whold=which(old);
 30     ch[old][whnow]=ch[k][whnow^1];
 31     if(ch[k][whnow^1])fa[ch[k][whnow^1]]=old;
 32     fa[old]=k,ch[k][whnow^1]=old,fa[k]=oldf;
 33     if(oldf) ch[oldf][whold]=k;
 34     if(!fa[k]) root=k;
 35     updata(old);updata(k);
 36     return;
 37 }
 38 inline void splay(int k,int aim){
 39     for(int i=fa[k];fa[k]!=aim;i=fa[k])
 40         rotate(fa[i]!=aim&&which(k)==which(i)?i:k);
 41     return;
 42 }
 43 int find(int k,int x){ //返回位置为x的书上面有多少本 
 44     if(!k) return 0;
 45     if(pos[k]==x){int res=siz[ch[k][0]];splay(k,0);return res;}
 46     if(pos[k]>x) return find(ch[k][0],x);
 47     int tmp=siz[ch[k][0]];
 48     return tmp+1+find(ch[k][1],x);
 49 }
 50 int kth(int now,int k){//返回第k本书的编号
 51     if(!now) return 0;
 52     if(siz[ch[now][0]]==k-1) return id[now];
 53     if(siz[ch[now][0]]>=k) return kth(ch[now][0],k);
 54     return kth(ch[now][1],k-siz[ch[now][0]]-1);
 55 }
 56 inline int get(int k,bool b){ //b为0返回前驱节点,b为1返回后继节点 
 57     if(!ch[k][b]) return 0;
 58     int now=ch[k][b];
 59     while(ch[now][b^1]) now=ch[now][b^1];
 60     return now;
 61 }
 62 void move(int s,bool b){
 63     find(root,bookpos[s]);
 64     pos[root]=bookpos[s]=b?++maxpos:--minpos;
 65     if(!ch[root][b]) return;
 66     if(!ch[root][b^1]){
 67         swap(ch[root][0],ch[root][1]); //!!
 68         return; 
 69     }
 70     book[bookpos[s]]=s;
 71     int nxt=get(root,b^1);
 72     if(!nxt){swap(ch[root][0],ch[root][1]);return;}
 73     splay(nxt,root);
 74     ch[nxt][b]=ch[root][b];
 75     fa[ch[root][b]]=nxt,ch[root][b]=0;
 76     updata(ch[root][b^1]);updata(root);
 77     return;
 78 }
 79 void nodeswap(int s,bool b){
 80     find(root,bookpos[s]);
 81     int nxt=get(root,b);
 82     if(!nxt) return;
 83     swap(id[nxt],id[root]);
 84     swap(book[pos[root]],book[pos[nxt]]);
 85     swap(bookpos[id[nxt]],bookpos[id[root]]);
 86     return;
 87 }
 88 int main(){
 89     char opt[10];
 90     int t1,t2;
 91     n=read(),m=read();
 92     minpos=m+1,maxpos=n+m;
 93     for(int i=m+1;i<=n+m;i++) book[i]=read(),bookpos[book[i]]=i;
 94     root=1;build(0,m+1,n+m);
 95     for(int i=1;i<=m;i++){
 96         scanf("%s",opt);
 97         if(opt[0]==T){
 98             t1=read();move(t1,0);
 99         }else if(opt[0]==B){
100             t1=read();move(t1,1);
101         }else if(opt[0]==I){
102             t1=read(),t2=read();
103             if(t2==-1) nodeswap(t1,0);
104             else if(t2==1) nodeswap(t1,1);
105         }else if(opt[0]==A){
106             t1=read();
107             printf("%d\n",find(root,bookpos[t1]));
108         }else{
109             t1=read();
110             printf("%d\n",kth(root,t1));
111         }
112     }
113     return 0;
114 }

 

以上是关于「luogu2596 」[ZJOI2006]书架的主要内容,如果未能解决你的问题,请参考以下文章

P2596 [ZJOI2006]书架

洛谷P2596 [ZJOI2006]书架splay

[ZJOI2006]书架(权值splay)

[Zjoi2006]Book 书架

[ZJOI2006]书架

[ZJOI 2006] 书架