• hdu 1890 Robotic Sort(splay 区间反转+删点)


    题目链接:hdu 1890 Robotic Sort

    题意:

    给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次。

    题解:

    典型的splay区间翻转+删点。

    我们把数据排序,然后记录一下每个数原来的位置,然后splay建树的时候用原来的位置来对应,这样val[i].second就直接是这个数在splay中的那个节点。

    (当然你也可以普通建树,然后手动记录位置)。

    然后我们把要找的那个数对应的节点旋转到根,然后根左边的size+i就是当前数的答案,然后翻转一下前面的数,再删除根。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;++i)
     3 using namespace std;
     4 
     5 const int N=1e5+7;
     6 int n,a[N],size[N],ch[N][2],f[N],tot,root;bool rev[N];
     7 pair<int,int>val[N];
     8 
     9 void rev1(int x){if(!x)return;swap(ch[x][0],ch[x][1]);rev[x]^=1;}
    10 
    11 void pb(int x){
    12     if(rev[x]){
    13         rev1(ch[x][0]);
    14         rev1(ch[x][1]);
    15         rev[x]=0;
    16     }
    17 }
    18 
    19 void up(int x){
    20     size[x]=1;
    21     if(ch[x][0])size[x]+=size[ch[x][0]];
    22     if(ch[x][1])size[x]+=size[ch[x][1]];
    23 }
    24 
    25 void rotate(int x){
    26     int y=f[x],w=ch[y][1]==x;
    27     ch[y][w]=ch[x][w^1];
    28     if(ch[x][w^1])f[ch[x][w^1]]=y;
    29     if(f[y]){
    30         int z=f[y];
    31         if(ch[z][0]==y)ch[z][0]=x;
    32         if(ch[z][1]==y)ch[z][1]=x;
    33     }
    34     f[x]=f[y];ch[x][w^1]=y;f[y]=x;up(y);
    35 }
    36 
    37 void splay(int x,int w){
    38     int s=1,i=x,y;a[1]=x;
    39     while(f[i])a[++s]=i=f[i];
    40     while(s)pb(a[s--]);
    41     while(f[x]!=w){
    42         y=f[x];
    43         if(f[y]!=w){if((ch[f[y]][0]==y)^(ch[y][0]==x))rotate(x);else rotate(y);}
    44         rotate(x);
    45     }
    46     if(!w)root=x;
    47     up(x);
    48 }
    49 
    50 void newnode(int &r,int fa,int k)
    51 {
    52     r=k,f[r]=fa,rev[r]=0,ch[r][0]=ch[r][1]=0;
    53 }
    54 
    55 void build(int &x,int l,int r,int fa){
    56     int mid=(l+r)>>1;
    57     newnode(x,fa,mid);
    58     if(l<mid)build(ch[x][0],l,mid-1,x);
    59     if(r>mid)build(ch[x][1],mid+1,r,x);
    60     up(x);
    61     return;
    62 }
    63 
    64 int getmax(int x)
    65 {
    66     pb(x);
    67     while(ch[x][1])x=ch[x][1],pb(x);
    68     return x;
    69 }
    70 
    71 void delroot()
    72 {
    73     if(ch[root][0])
    74     {
    75         int m=getmax(ch[root][0]);
    76         splay(m,root);
    77         ch[m][1]=ch[root][1];
    78         f[ch[root][1]]=m;
    79         root=m,f[m]=0,up(m);
    80     }else root=ch[root][1],f[root]=0;
    81 }
    82 
    83 int main(){
    84     while(scanf("%d",&n),n)
    85     {
    86         F(i,1,n)scanf("%d",&val[i].first),val[i].second=i;
    87         sort(val+1,val+1+n),build(root,1,n,0);
    88         F(i,1,n-1)
    89         {
    90             splay(val[i].second,0);
    91             rev1(ch[root][0]);
    92             printf("%d ",i+size[ch[root][0]]);
    93             delroot();
    94         }
    95         printf("%d
    ",n);    
    96     }
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    共享无法访问问题,通过ip地址或者主机名无法访问目的主机
    开机系统更新,一直停在?%处,无法进入系统
    win7电脑访问内网地址报错0x800704cf,0x80070035解决方法
    电脑共享--问题汇总
    win10域账户用户时间无法和域服务器同步
    卸载WPS后,原office出现各种问题,报错,图标混乱
    局域网新装电脑主机网络断断连连解决方案
    win10主机无法进入本地共享,“没有权限”
    win10安装部分软件报错“应用程序无法启动,应用程序并行配置不正确,或使用命令行sxstrace.exe”
    【日常修机】打印机故障维护
  • 原文地址:https://www.cnblogs.com/bin-gege/p/6285908.html
Copyright © 2020-2023  润新知