山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

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.好久之前就想切掉这道题了,但一直苦于没有正确的姿势=-=

 

posted on 2016-03-19 11:45  hahalidaxin  阅读(200)  评论(0编辑  收藏  举报