HDU 1890 Robotic Sort(splay)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 1890 Robotic Sort(splay)相关的知识,希望对你有一定的参考价值。
【题目链接】
http://acm.hdu.edu.cn/showproblem.php?pid=1890
【题意】
给定一个序列,每次将i..P[i]反转,然后输出P[i],P[i]定义为当前数字i的所在位置。相等的两个数排序后相对位置不变。
【思路】
由于相对位置不变,所以可以根据数值与位置重编号。
依旧使用直接定位从上到下旋转至根的splay写法。每次将i结点旋转至根,则答案为左儿子大小+i,然后将i删掉合并左右儿子。
需要注意合并时判断左右儿子是否为空,以及各种pushdown下传标记。
【代码】
1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<vector> 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt) 10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 11 using namespace std; 12 13 typedef long long ll; 14 const int N = 5e5+10; 15 16 ll read() { 17 char c=getchar(); 18 ll f=1,x=0; 19 while(!isdigit(c)) { 20 if(c==‘-‘) f=-1; c=getchar(); 21 } 22 while(isdigit(c)) 23 x=x*10+c-‘0‘,c=getchar(); 24 return x*f; 25 } 26 27 struct Node *null; 28 struct Node { 29 int v,s,rev; 30 Node *ch[2],*fa; 31 void init(int x) { 32 v=x; 33 s=rev=0; 34 ch[0]=ch[1]=fa=null; 35 } 36 void pushdown() { 37 if(rev) { 38 swap(ch[0],ch[1]); 39 ch[0]->rev^=1; ch[1]->rev^=1; 40 rev=0; 41 } 42 } 43 void maintain() { 44 s=ch[0]->s+ch[1]->s+1; 45 } 46 } nodepool[N],*node[N]; 47 48 void rot(Node* o,int d) { 49 Node *k=o->ch[d],*tmp=null; 50 o->ch[d]=k->ch[d^1]; 51 if((tmp=k->ch[d^1])!=null) tmp->fa=o; 52 k->ch[d^1]=o; 53 if((tmp=o->fa)!=null) tmp->ch[tmp->ch[1]==o]=k; 54 o->fa=k; k->fa=tmp; 55 } 56 Node *st[N<<3]; 57 void up_push(Node* u) { 58 int top=0; 59 while(u!=null) 60 st[++top]=u,u=u->fa; 61 while(top) 62 st[top--]->pushdown(); 63 } 64 void splay(Node* o,Node* des=null) { 65 up_push(o); 66 Node *nf,*nff; 67 while(o!=des && (nf=o->fa)!=des) { 68 nff=nf->fa; 69 if(nff==des) rot(nf,nf->ch[1]==o),nf->maintain(); 70 else { 71 int d1=nf->ch[1]==o,d2=nff->ch[1]==nf; 72 if(d1==d2) rot(nff,d2),rot(nf,d1); 73 else rot(nf,d1),rot(nff,d2); 74 nff->maintain(),nf->maintain(); 75 } 76 } 77 o->maintain(); 78 } 79 void reverse(Node* o) { 80 swap(o->ch[0],o->ch[1]); 81 o->ch[0]->rev^=1; 82 o->ch[1]->rev^=1; 83 } 84 Node* getbound(Node* o,int d) { 85 o->pushdown(); 86 if(o->ch[0]==null&&o->ch[1]==null) return o; 87 if(o->ch[d]!=null) return getbound(o->ch[d],d); 88 else return o; 89 } 90 void merge(Node* u,Node* v) { 91 if(u->ch[1]==null) u->ch[1]=v; 92 else { 93 u=getbound(u,1); 94 splay(u); 95 u->ch[1]=v; 96 } 97 v->fa=u; u->maintain(); 98 } 99 100 int n,a[N]; 101 102 Node* build(int l,int r,Node* fa) { 103 if(l>r) return null; 104 int mid=l+r>>1; 105 Node* o=node[a[mid]]; 106 o->fa=fa; 107 o->v=a[mid]; 108 o->ch[0]=build(l,mid-1,o); 109 o->ch[1]=build(mid+1,r,o); 110 o->maintain(); 111 return o; 112 } 113 struct snode { 114 int a,rank; 115 bool operator < (const snode& rhs) const { 116 return a<rhs.a||(a==rhs.a&&rank<rhs.rank); 117 } 118 } nodes[N]; 119 120 int main() 121 { 122 //freopen("in.in","r",stdin); 123 //freopen("out.out","w",stdout); 124 while(n=read(),n) { 125 null=new Node(); 126 FOR(i,1,n) { 127 a[i]=read(); 128 nodes[i]=(snode){a[i],i}; 129 node[i]=&nodepool[i]; 130 nodepool[i].init(0); 131 } 132 sort(nodes+1,nodes+n+1); 133 FOR(i,1,n) a[nodes[i].rank]=i; 134 build(1,n,null); 135 FOR(i,1,n-1) { 136 Node* o=node[i]; 137 splay(o); 138 printf("%d ",o->ch[0]->s+i); 139 Node *lc=o->ch[0],*rc=o->ch[1]; 140 o->ch[0]=o->ch[1]=null; 141 lc->fa=rc->fa=null; 142 if(lc!=null) { 143 lc->pushdown(); 144 if(rc!=null) rc->pushdown(); 145 reverse(lc); 146 merge(lc,rc); 147 } 148 } 149 printf("%d\n",n); 150 } 151 return 0; 152 }
P.S.好久之前就想切掉这道题了,但一直苦于没有正确的姿势=-=
以上是关于HDU 1890 Robotic Sort(splay)的主要内容,如果未能解决你的问题,请参考以下文章
HDU1890 Robotic Sort[splay 序列]
HDU 1890 - Robotic Sort - [splay][区间反转+删除根节点]