AlenaNuna

导航

fhq_treap || BZOJ1861: [Zjoi2006]Book 书架 || Luogu P2596 [ZJOI2006]书架

题面:P2596 [ZJOI2006]书架

题解:记录每本书对应的节点编号

普通fhq_treap无法查询一个权值的排名,所以在普通fhq_treap上多记录每个节点的父亲(可加在pushup函数中),

查询时从该节点开始逐步往上跳,记录答案。

其他操作都依附在该排名上。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<cstdlib>
  5 using namespace std;
  6 inline int rd(){
  7     int x=0,f=1;char c=getchar();
  8     while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
  9     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
 10     return f*x;
 11 }
 12 const int maxn=(8e4)+50;
 13 int N,M,lc[maxn],rc[maxn],val[maxn],pr[maxn],tot=0,siz[maxn];
 14 int u,rt=0,s,t,x,y,z,id[maxn],fa[maxn],k;
 15 //id[i]表示编号为i的书所在的节点编号 
 16 char o[15];
 17 inline int New_node(int x){
 18     val[++tot]=x;
 19     siz[tot]=1;
 20     pr[tot]=rand();
 21     return tot;
 22 }
 23 inline void Pushup(int x){
 24     siz[x]=siz[lc[x]]+siz[rc[x]]+1;
 25     fa[lc[x]]=fa[rc[x]]=x;
 26     return;
 27 }
 28 inline void Split(int now,int k,int &x,int &y){
 29     if(!now){
 30         x=y=fa[x]=fa[y]=0;
 31         return;
 32     }
 33     if(siz[lc[now]]+1<=k){
 34         x=now;
 35         Split(rc[now],k-siz[lc[now]]-1,rc[now],y);
 36     }
 37     else {        
 38         y=now;
 39         Split(lc[now],k,x,lc[now]);
 40     }
 41     Pushup(now);
 42     return;
 43 }
 44 inline int Merge(int x,int y){
 45     if(!x||!y){
 46         fa[x]=fa[y]=x+y;
 47         return x+y;
 48     }
 49     if(pr[x]<pr[y]){
 50         rc[x]=Merge(rc[x],y);
 51         Pushup(x);
 52         return x;
 53     }
 54     else{
 55         lc[y]=Merge(x,lc[y]);
 56         Pushup(y);
 57         return y;
 58     }
 59 }
 60 inline int Find(int x){//寻找x节点上有多少书
 61     int sum=0;
 62     sum+=siz[lc[x]];
 63     while(x!=rt){
 64         if(rc[fa[x]]==x)sum+=siz[lc[fa[x]]]+1;
 65         x=fa[x];
 66     }
 67     return sum;
 68 }
 69 inline int Query(int k){
 70     int now=rt;
 71     while(now){
 72         if(k<=siz[lc[now]])now=lc[now];
 73         else if(k==siz[lc[now]]+1)return now;
 74         else k-=siz[lc[now]]+1,now=rc[now];
 75     }
 76     return 0;
 77 }
 78 int main(){
 79     srand(20030304);
 80     N=rd();M=rd();
 81     for(int i=1;i<=N;i++){
 82         u=rd();
 83         rt=Merge(rt,id[u]=New_node(u));
 84     }
 85     while(M--){
 86         scanf("%s",o); s=rd();
 87         if(o[0]=='T'){
 88             k=Find(id[s]);
 89             Split(rt,k+1,x,z);
 90             Split(x,k,x,y);
 91             rt=Merge(Merge(x,Merge(lc[y],rc[y])),z);
 92             rt=Merge(id[s],rt);
 93         }
 94         else if(o[0]=='B'){
 95             k=Find(id[s]);
 96             Split(rt,k+1,x,z);
 97             Split(x,k,x,y);
 98             rt=Merge(Merge(x,Merge(lc[y],rc[y])),z);
 99             rt=Merge(rt,id[s]);
100         }
101         else if(o[0]=='I'){
102             t=rd();
103             k=Find(id[s]);
104             Split(rt,k+1,x,z);
105             Split(x,k,x,y);
106             rt=Merge(Merge(x,Merge(lc[y],rc[y])),z);
107             Split(rt,k+t,x,y);
108             rt=Merge(Merge(x,id[s]),y);
109         }
110         else if(o[0]=='A'){
111             printf("%d\n",Find(id[s]));    
112         }
113         else {//Q
114             printf("%d\n",val[Query(s)]);    
115         }
116     }
117     return 0;
118 }

By:AlenaNuna

posted on 2019-05-28 20:58  AlenaNuna  阅读(205)  评论(0编辑  收藏  举报