zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    oracle批量更新之使用游标进行分批次更新的5种方式及速度比对
    oracle 两个网络不通的远程数据库如何将一个库中的表数据导入到另一个库中?
    惠星球史上最全攻略,手把手带你飞
    oracle 批量删除表数据的4种方式
    zabbix client安装配置执行
    Neural Networks for Machine Learning by Geoffrey Hinton (4)
    代码坏味道之过长的參数列
    Codeforces Round #313 (Div. 1) Gerald&#39;s Hexagon
    java界面编程(3) ------ 控制布局
    数据结构实验之队列一:排队买饭
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/8456607.html
Copyright © 2011-2022 走看看