HDU 1890 Robotic Sort

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

【题意】
    给你n个数,每次将第i个位置到第i大的数所在位置之间的数进行翻转,模拟一种排序的操作,输出的是第i次操作第i大的数所在的位置。

【分析】

     这题和2012天津现场赛的K题类似,用Splay Tree 来记录节点间的相对左右关系,树的中序就是原数列。每个节点记录以自己为根的子树有多少个节点,这样就可以很快知道一个数的左边右多少树了。每次操作后要删除第i大数的节点,根据题目要求元素要用stable_sort排序,并记录节点指针地址,这样的话第i个答案就是 i+path[i-1].t->left->data。

     由于还要求将一段数列逆转,对于这段数列中的每个元素节点,其实就是把左右子树对调下就可以了。为了提高效率,这里要像线段树样打懒惰标记,就涉及到标记的传递和数据的更新了,一定要按合适的顺序和在合适的地方来操作。另外删除节点的时候是直接利用节点地址的,那无法保证节点上方的懒惰标记已经传递下来,所以先要从根到当前节点传递下。

 

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <algorithm>
  5 using namespace std;
  6 struct pair
  7 {
  8     int data;
  9     void *t;
 10     bool operator <(const pair & a) const
 11     {
 12         return data<a.data;
 13     }
 14 }path[100002];
 15 struct spt
 16 {
 17     spt(){root=NULL;}
 18     struct node
 19     {
 20         int data;
 21         bool flip;
 22         node *left,*right,*father;
 23         node(int d=0,node* a=NULL,node *b=NULL,node *c=NULL):data(d),left(a),right(b),father(c),flip(false){}
 24     }*root;
 25     void pushup(node *root)
 26     {
 27         if (root==NULL) return;
 28         pushup(root->father);
 29         pushdown(root);
 30     }
 31     void pushdown(node *k)
 32     {
 33         if (k==NULL) return;
 34         if (!k->flip) return;
 35         node *t=k->left;
 36         k->left=k->right;
 37         k->right=t;
 38         if (k->left) k->left->flip^=1;
 39         if (k->right) k->right->flip^=1;
 40         k->flip^=1;
 41     }
 42     void update(node *k)
 43     {
 44         k->data=1;
 45         if (k->left) k->data+=k->left->data;
 46         if (k->right) k->data+=k->right->data;
 47     }
 48     void zig(node *k)
 49     {
 50         node* fa=k->father;
 51         pushdown(fa);
 52         pushdown(k);
 53         fa->left=k->right;
 54         if (k->right) k->right->father=fa;
 55         k->right=fa;
 56         k->father=fa->father;
 57         fa->father=k;
 58         update(fa);
 59         update(k);
 60         if (!k->father) return;
 61         if (k->father->left==fa)
 62             k->father->left=k;
 63         else
 64             k->father->right=k;
 65         update(k->father);
 66     }
 67     void zag(node *k)
 68     {
 69         node* fa=k->father;
 70         pushdown(fa);
 71         pushdown(k);
 72         fa->right=k->left;
 73         if (k->left) k->left->father=fa;
 74         k->left=fa;
 75         k->father=fa->father;
 76         fa->father=k;
 77         update(fa);
 78         update(k);
 79         if (!k->father) return;
 80         if (k->father->left==fa)
 81             k->father->left=k;
 82         else
 83             k->father->right=k;
 84         update(k->father);
 85     }
 86     void splay(node *k,node *&root)
 87     {
 88         pushdown(k);
 89         while (k->father)
 90         {
 91             node *fa=k->father;
 92             if (fa->father==NULL)
 93             {
 94                 if (k==fa->left) zig(k);
 95                 else zag(k);
 96             }
 97             else
 98             {
 99                 node *gf=fa->father;
100                 if (fa==gf->left && k==fa->left)
101                 {
102                     zig(fa);
103                     zig(k);
104                 }
105                 if (fa==gf->left && k==fa->right)
106                 {
107                     zag(k);
108                     zig(k);
109                 }
110                 if (fa==gf->right && k==fa->left)
111                 {
112                     zig(k);
113                     zag(k);
114                 }
115                 if (fa==gf->right && k==fa->right)
116                 {
117                     zag(fa);
118                     zag(k);
119                 }
120             }
121         }
122         root=k;
123     }
124     node *findmax(node *&p)
125     {
126         node *t=p;
127         pushdown(t);
128         while (t->right) {t=t->right;pushdown(t);}
129         splay(t,p);
130         return t;
131     }
132     node* join(node *a,node *b)
133     {
134         if (a) {a->flip^=1;pushdown(a); a->father=NULL; }
135         if (b) { pushdown(b);b->father=NULL;}
136        if (!a || !b) return (node *)((int)a|(int)b);
137         node *t=findmax(a);
138         t->right=b;
139         b->father=t;
140         update(t);
141         return t;
142     }
143     int remove(node *q)
144     {
145         pushup(q);
146         splay(q,root);
147         node *tem=root;
148         int tt=0;
149         if (root->left) tt=root->left->data;
150         root=join(root->left,root->right);
151         delete tem;
152         return tt;
153     }
154     void del(node *p)
155     {
156         if (p==NULL) return;
157         del(p->left);
158         del(p->right);
159         delete p;
160     }
161     void build(int l,int r,node *&root)
162     {
163         if (l>r || l<0) return ;
164         int mid=(l+r)>>1;
165         root=new node;
166         build(l,mid-1,root->left);
167         if (root->left) root->left->father=root;
168         build(mid+1,r,root->right);
169         if (root->right) root->right->father=root;
170         path[mid].t=(void *)root;
171         update(root);
172     }
173     ~spt(){del(root);}
174 }*mysp;
175 
176 int main()
177 {
178    int n;
179    while (~scanf("%d",&n) && n)
180    {
181        mysp=new spt;
182        for (int i=0;i<n;++i)
183        {
184            int t;
185            scanf("%d",&t);
186            path[i].data=t;
187        }
188        mysp->build(0,n-1,mysp->root);
189        stable_sort(path,path+n);
190        for (int i=0;i<n-1;++i)
191        {
192            printf("%d ",i+mysp->remove((spt::node *)path[i].t)+1);
193        }
194        printf("%d\n",mysp->remove((spt::node *)path[n-1].t)+n);
195        delete mysp;
196    }
197 }
代码

 

 

 

posted @ 2013-08-16 16:16  wuminye  阅读(361)  评论(0编辑  收藏  举报