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 }