• HDU1890 Robotic Sort Splay tree反转,删除


      题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890

      题目中涉及数的反转和删除操作,需要用Splay tree来实现。首先对数列排序,得到每个数在数列中的下标x。Splay tree的每个节点标记以它为根的子树是否需要反转,用到懒惰操作,保证nlogn,在每次操作的时候Push_Down()和Push_Up。在建树的时候是数的下标为节点标号建立数,如果要询问数num[i],则把num[i]在数列中的下标旋转到根节点root,size[ch[root][0]]+已经排好序的数的数目就是答案。注意,这里因为涉及到数的反转操作,因此在Splay()操作的时候,应该先Push_Down(),然后再判断旋转操作。。

      1 //STATUS:C++_AC_256MS_2700KB
      2 #include <functional>
      3 #include <algorithm>
      4 #include <iostream>
      5 //#include <ext/rope>
      6 #include <fstream>
      7 #include <sstream>
      8 #include <iomanip>
      9 #include <numeric>
     10 #include <cstring>
     11 #include <cassert>
     12 #include <cstdio>
     13 #include <string>
     14 #include <vector>
     15 #include <bitset>
     16 #include <queue>
     17 #include <stack>
     18 #include <cmath>
     19 #include <ctime>
     20 #include <list>
     21 #include <set>
     22 #include <map>
     23 using namespace std;
     24 //using namespace __gnu_cxx;
     25 //define
     26 #define pii pair<int,int>
     27 #define mem(a,b) memset(a,b,sizeof(a))
     28 #define lson l,mid,rt<<1
     29 #define rson mid+1,r,rt<<1|1
     30 #define PI acos(-1.0)
     31 //typedef
     32 typedef __int64 LL;
     33 typedef unsigned __int64 ULL;
     34 //const
     35 const int N=100010;
     36 const int INF=0x3f3f3f3f;
     37 const int MOD=100000,STA=8000010;
     38 const LL LNF=1LL<<60;
     39 const double EPS=1e-8;
     40 const double OO=1e15;
     41 const int dx[4]={-1,0,1,0};
     42 const int dy[4]={0,1,0,-1};
     43 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
     44 //Daily Use ...
     45 inline int sign(double x){return (x>EPS)-(x<-EPS);}
     46 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
     47 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
     48 template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
     49 template<class T> inline T Min(T a,T b){return a<b?a:b;}
     50 template<class T> inline T Max(T a,T b){return a>b?a:b;}
     51 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
     52 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
     53 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
     54 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
     55 //End
     56 
     57 #define Key_value ch[ch[root][1]][0]
     58 int pre[N],ch[N][2];  //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
     59 int sz[N],st[N];   //子树规模,内存池
     60 int root,tot,top;   //根节点,根节点数量,内存池容量
     61 //题目特定数据
     62 struct Node{
     63     int num,idx;
     64 }nod[N];
     65 bool rev[N];
     66 int n;
     67 //debug部分copy from hh
     68 void Treaval(int x) {
     69     if(x) {
     70         Treaval(ch[x][0]);
     71         printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d rev = %2d
    ",x,ch[x][0],ch[x][1],pre[x],sz[x],rev[x]);
     72         Treaval(ch[x][1]);
     73     }
     74 }
     75 void debug() {printf("%d
    ",root);Treaval(root);}
     76 //以上Debug
     77 //新建一个结点
     78 void NewNode(int &x,int fa,int k)
     79 {
     80  //   if(top)x=st[--top];
     81  //   else x=++tot;
     82     x=k;
     83     pre[x]=fa;
     84     sz[x]=1;
     85     rev[x]=0;
     86     ch[x][0]=ch[x][1]=0;  //左右孩子为空
     87 }
     88 
     89 void Push_Up(int x)
     90 {
     91     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
     92 }
     93 
     94 void Push_Down(int x)
     95 {
     96     if(rev[x]){
     97         rev[ch[x][0]]^=1;
     98         rev[ch[x][1]]^=1;
     99         swap(ch[x][0],ch[x][1]);
    100         rev[x]=0;
    101     }
    102 }
    103 //旋转,kind为1为右旋,kind为0为左旋
    104 void Rotate(int x,int kind)
    105 {
    106     int y=pre[x],z=pre[y];
    107     Push_Down(y);
    108     Push_Down(x);  //先把y的标记向下传递,再把x的标记往下传递
    109     //类似SBT,要把其中一个分支先给父节点
    110     ch[y][!kind]=ch[x][kind];
    111     pre[ch[x][kind]]=y;
    112     //如果父节点不是根结点,则要和父节点的父节点连接起来
    113     if(z)ch[z][ch[z][1]==y]=x;
    114     pre[x]=z;
    115     ch[x][kind]=y;
    116     pre[y]=x;
    117     Push_Up(y);  //维护y结点,不要维护x节点,x节点会再次Push_Down,最后维护一下x节点即可
    118 }
    119 //Splay调整,将根为r的子树调整为goal
    120 void Splay(int x,int goal)
    121 {
    122     int y,z,kind;
    123     while(pre[x]!=goal){
    124         //父节点即是目标位置,goal为0表示,父节点就是根结点
    125         y=pre[x];
    126         Push_Down(pre[y]);Push_Down(y);Push_Down(x);   //设计到反转操作,要先更新,然后在判断!!
    127         if(pre[y]==goal){
    128             Rotate(x,ch[y][0]==x);
    129         }
    130         else {
    131             kind=ch[pre[y]][0]==y;
    132             //两个方向不同,则先左旋再右旋
    133             if(ch[y][kind]==x){
    134                 Rotate(x,!kind);
    135                 Rotate(x,kind);
    136             }
    137             //两个方向相同,相同方向连续两次
    138             else {
    139                 Rotate(y,kind);
    140                 Rotate(x,kind);
    141             }
    142         }
    143     }
    144     //更新根结点
    145     Push_Up(x);
    146     if(goal==0)root=x;
    147 }
    148 //建树,中间结点先建立,然后分别对区间两端在左右子树建立
    149 void BuildTree(int &x,int l,int r,int fa)
    150 {
    151     if(l>r)return;
    152     int mid=(l+r)>>1;
    153     NewNode(x,fa,mid);
    154     BuildTree(ch[x][0],l,mid-1,x);
    155     BuildTree(ch[x][1],mid+1,r,x);
    156     Push_Up(x);
    157 }
    158 
    159 int cmp(Node a,Node b)
    160 {
    161     return a.num!=b.num?a.num<b.num:a.idx<b.idx;
    162 }
    163 
    164 void Init()
    165 {
    166     root=tot=top=0;
    167     ch[root][0]=ch[root][1]=pre[0]=sz[0]=rev[0]=0;
    168 
    169     for(int i=1;i<=n;i++){
    170         scanf("%d",&nod[i].num);
    171         nod[i].idx=i;
    172     }
    173     sort(nod+1,nod+n+1,cmp);
    174     BuildTree(root,1,n,0);
    175 }
    176 
    177 int Get_Max(int x)
    178 {
    179     Push_Down(x);
    180     while(ch[x][1]){
    181         x=ch[x][1];
    182         Push_Down(x);
    183     }
    184     return x;
    185 }
    186 
    187 void Remove()
    188 {
    189     if(ch[root][0]==0){
    190         root=ch[root][1];
    191         pre[root]=0;
    192     }
    193     else {
    194         int x=Get_Max(ch[root][0]);
    195         Splay(x,root);
    196         ch[x][1]=ch[root][1];
    197         pre[ch[root][1]]=x;
    198         root=x;
    199         pre[root]=0;
    200         Push_Up(root);
    201     }
    202 }
    203 
    204 int main()
    205 {
    206  //   freopen("in.txt","r",stdin);
    207     int i,j;
    208     while(~scanf("%d",&n) && n)
    209     {
    210         Init();
    211         for(i=1;i<n;i++){
    212             Splay(nod[i].idx,0);
    213             rev[ch[root][0]]^=1;
    214             printf("%d ",i+sz[ch[root][0]]);
    215             Remove();
    216         }
    217         printf("%d
    ",n);
    218     }
    219     return 0;
    220 }
  • 相关阅读:
    2018.11.15 RF antenna impedance-matching
    2018.11.14 Chopin’s
    2018.11.13 N4010A 通信设置
    2018.11.12 RF debug
    2018.11 企业战略课堂笔记4 -内部条件分析
    2018.11 企业战略课堂笔记3 五力模型
    2018.11 企业战略课堂笔记2 SWOT-4C战略
    2018.11 企业战略课堂笔记1 概论
    PyQt(Python+Qt)学习随笔:QTabWidget选项卡部件操作控制类属性movable和tabsClosable介绍
    PyQt(Python+Qt)学习随笔:QTabWidget选项卡部件外观展示类属性elideMode、documentMode、tabBarAutoHide、tabShape介绍
  • 原文地址:https://www.cnblogs.com/zhsl/p/3210206.html
Copyright © 2020-2023  润新知