[hdu1890] Robotic Sort [Splay]

题面:

传送门

思路:

一看到要在序列里面翻转一段区间,就知道要使用splay了

但是这道题涉及到一个问题:如何在通过序列位置定义的splay上面查找最小值?

(对splay的这种用法不熟悉的可以参考这篇博客

这里提供两种方法:

第一种,对于每一个splay节点,我们把它的键值w设为它在原序列中的排名(注意:相同的数排名不同,这一步需要离散化)

然后再保存一个min值即可

这样每一次我们想要在splay树中找大小最小的节点,只要不断地往min小一些的方向去走即可

然后,当我们做完一次操作(翻转)以后,因为前面已经排好序的元素我们其实不用再管它了,所以可以把这个元素从splay中删掉

这样,以后每次要翻转到前面去的,都是当前splay里面最小的那个元素了

这种方式的优点在于找最小值的过程比较直观,但是需要多维护一个min值,调试难度略大

第二种,不保存min值,而是选取另一个方法:映射

在输入数据、离散化结束以后,我们用二叉构造的方式建splay,这个过程中会给每一个元素赋一个“这个元素在splay数组中的下标”

我们建立一个pos数组来保存从元素到这个数组下标的映射,即pos[i]的值代表“第i个元素在splay数组当中的下标”

这样的话,每一次操作时我们可以通过把这个已知的元素splay到根的方式,得到它在当前splay中的排名,用这个排名加上前面已经处理完了的数的个数,就得到了当前未操作序列中最小元素(也就是下一步需要操作的元素)的位置了

然后再把它旋转、删除即可

这种方式的优点在于没用在splay上维护更多量,缺点是时间效率可能会比较低

Code:

由于博主比较懒,虽然两种方法都想到了,但是只写了第二种......

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define inf 1e9
  6 using namespace std;
  7 inline int read(){
  8     int re=0,flag=1;char ch=getchar();
  9     while(ch>'9'||ch<'0'){
 10         if(ch=='-') flag=-1;
 11         ch=getchar();
 12     }
 13     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
 14     return re*flag;
 15 }
 16 int n,m,cnt,root,pos[200010];
 17 int fa[200010],ch[200010][2],rev[200010],siz[200010],w[200010];
 18 struct node{
 19     int val,num;
 20 }a[200010];
 21 bool cmp(node l,node r){
 22     if(l.val!=r.val) return l.val<r.val;
 23     else return l.num<r.num;
 24 }
 25 bool cmp2(node l,node r){
 26     return l.num<r.num;
 27 }
 28 void _swap(int &l,int &r){l^=r;r^=l;l^=r;}
 29 void update(int x){
 30     siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
 31 }
 32 void pushrev(int x){
 33     if(!x) return;
 34     _swap(ch[x][0],ch[x][1]);
 35     rev[x]^=1;
 36 }
 37 int push(int x){
 38     if(x&&rev[x]){
 39         pushrev(ch[x][0]);pushrev(ch[x][1]);
 40         rev[x]=0;
 41     }
 42     return 1;
 43 }
 44 int get(int x){return ch[fa[x]][1]==x;}
 45 void rotate(int x){
 46     int f=fa[x],ff=fa[f],son=get(x);
 47     push(f);push(x);
 48     ch[f][son]=ch[x][son^1];
 49     if(ch[f][son]) fa[ch[f][son]]=f;
 50     fa[f]=x;ch[x][son^1]=f;
 51     fa[x]=ff;
 52     if(ff) ch[ff][ch[ff][1]==f]=x;
 53     update(f);update(x);
 54 }
 55 void splay(int x,int to){
 56     push(x);
 57     for(int f;(f=fa[x])&&(f!=to);rotate(x)){
 58         push(fa[f]);push(f);push(x);
 59         if(fa[f]!=to)
 60             rotate((get(x)==get(f))?f:x);
 61     }
 62     update(x);
 63     if(!to) root=x;
 64 }
 65 int build(int l,int r,int f){
 66     if(l>r) return 0;
 67     int cur=++cnt,mid=(l+r)>>1;
 68     fa[cur]=f;w[cur]=a[mid].val;siz[cur]=1;pos[a[mid].val]=cur;
 69     ch[cur][0]=build(l,mid-1,cur);
 70     ch[cur][1]=build(mid+1,r,cur);
 71 //    cout<<"finish build "<<mid<<ends<<cur<<ends<<ch[cur][0]<<ends<<ch[cur][1]<<endl;
 72     update(cur);return cur;
 73 }
 74 void dfs(int u){
 75     if(!u) return;
 76     dfs(ch[u][0]);
 77     cout<<u<<ends<<w[u]<<ends<<rev[u]<<ends<<ch[u][0]<<ends<<ch[u][1]<<ends<<siz[u]<<endl;
 78     dfs(ch[u][1]);
 79 }
 80 void init(){
 81     memset(fa,0,sizeof(fa));memset(ch,0,sizeof(ch));memset(rev,0,sizeof(rev));
 82     memset(siz,0,sizeof(siz));memset(w,0,sizeof(w));memset(a,0,sizeof(a));
 83     root=0,cnt=0;
 84 }
 85 int suf(){
 86     push(root);
 87     int x=ch[root][1];
 88     while(push(x)&&ch[x][0]) x=ch[x][0];
 89     return x;
 90 }
 91 void reverse(int p){
 92 //    cout<<"reverse "<<p<<endl;
 93     splay(pos[p],0);
 94     printf("%d",p-1+siz[ch[root][0]]);
 95     if(p!=n) printf(" ");
 96     int x=pos[0],y=suf();
 97     splay(x,0);splay(y,root);
 98 //    dfs(root);
 99     pushrev(ch[y][0]);
100 }
101 void del(int p){
102 //    cout<<"del "<<p<<endl;
103     splay(pos[p],0);int tmp=suf();
104     splay(pos[0],0);splay(tmp,root);
105     fa[ch[tmp][0]]=0;ch[tmp][0]=0;update(tmp);update(pos[0]);
106 //    dfs(root);
107 //    cout<<"dell "<<p<<endl;
108 //    fa[ch[root][1]]=ch[root][0];ch[ch[root][0]][1]=ch[root][1];
109 //    update(ch[root][0]);root=ch[root][0];fa[root]=0;
110 //    fa[ch[root][0]]=tmp;ch[tmp][0]=ch[root][0];
111 //    update(tmp);root=tmp;fa[tmp]=0;
112 //    dfs(root);
113 }
114 int main(){
115 //    freopen("a.txt","w",stdout);
116     int i,t1;
117     while(n=read()){
118         init();
119         for(i=1;i<=n;i++) a[i].val=read(),a[i].num=i;
120         sort(a+1,a+n+1,cmp);
121 //        for(i=1;i<=n;i++) cout<<a[i].val<<ends<<a[i].num<<endl;
122         for(i=1;i<=n;i++) a[i].val=i;
123         sort(a+1,a+n+1,cmp2);
124         a[0].val=0;a[n+1].val=n+1;
125 //        for(i=0;i<=n+1;i++) cout<<a[i].val<<ends;cout<<endl;
126         root=build(0,n+1,root);
127         for(i=1;i<=n;i++){
128             reverse(i);del(i);
129         }
130         printf("
");
131     }
132 }
原文地址:https://www.cnblogs.com/dedicatus545/p/8456607.html