http://acm.hdu.edu.cn/showproblem.php?pid=1890
给一个长度为N(N<10,000)的数列,每次选取值最小的元素并翻转前面的数列,然后删除这个元素。请在每次操作之前输出这个最小元素的位置。
这里的splay应用是:放弃了元素之间的优先级,完全模拟一个数组(像笛卡尔树那样)
要解决一些问题:
1. 如何查找元素最小的元素? 记录最小值? NO! 数列的数组下标和splay的下标是一样的!!!!
2. 如何翻转一个区间? 先把这个区间“抽”出来,然后在这个区间的代表节点上加一个标记,传递标记的时候就旋转左右子树。
3. 如何删除节点? 找到节点的前驱与后继,然后通过splay前驱与后继把这个节点“抽”出来。
4. 如何在向上splay的时候传递懒惰标记? 看我之前一篇题解吧! 在splay之前更新所有的父亲节点!
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 #define inf (1<<29) 7 const int maxn = 100010; 8 int n , splaysz; 9 struct node { 10 int p,chd[2],sz,flag; 11 node (int P=0) { 12 chd[0]=chd[1]=0;sz=0; 13 p = P; flag = 0; 14 } 15 }tree[maxn]; 16 struct sample { 17 int id , v; 18 bool operator < (sample b) const { 19 return v==b.v?id<b.id:v<b.v; 20 } 21 }num[maxn]; 22 inline void sc(int y,int x,int p) { tree[y].chd[p]=x;tree[x].p=y; } 23 inline void update(int x) { 24 tree[x].sz=tree[tree[x].chd[0]].sz+tree[tree[x].chd[1]].sz+1; 25 } 26 inline void rot(int x) { 27 int y = tree[x].p; 28 int w = tree[y].chd[1] == x; 29 sc(tree[y].p,x,tree[tree[y].p].chd[1]==y); 30 sc(y,tree[x].chd[w^1],w); 31 sc(x,y,w^1); 32 update(y); 33 update(x); 34 } 35 void pushup(int x) { 36 if(tree[x].flag) { 37 tree[x].flag = 0; 38 swap(tree[x].chd[0],tree[x].chd[1]); 39 tree[tree[x].chd[0]].flag ^= 1; 40 tree[tree[x].chd[1]].flag ^= 1; 41 } 42 } 43 void dfs(int x) { 44 if(!x) return; 45 dfs(tree[x].p); 46 pushup(x); 47 } 48 void splay(int x,int rt) { 49 dfs(x); 50 while(tree[x].p!=rt) { 51 int y = tree[x].p; 52 int w = tree[y].chd[1]==x; 53 if(tree[y].p != rt && tree[tree[y].p].chd[w]==y) rot(y); 54 rot(x); 55 } 56 } 57 void insert(int x) { 58 sc(x-1,x,1); 59 tree[x].chd[0] = tree[x].chd[1] = tree[x].flag = 0; 60 splay(x , 0); 61 } 62 int cal(int x) { 63 splay(x , 0); 64 int ans = tree[tree[x].chd[0]].sz + 1; 65 tree[tree[x].chd[0]].flag ^= 1; 66 int u = tree[x].chd[0]; 67 int v = tree[x].chd[1]; 68 if(u == 0) sc(0 , v , 1); 69 else if(v == 0) sc(0 , u , 1); 70 else { 71 pushup(u); pushup(v); 72 while(tree[u].chd[1]) { u=tree[u].chd[1];pushup(u); } 73 while(tree[v].chd[0]) { v=tree[v].chd[0];pushup(v); } 74 splay(u,0); splay(v,u); 75 // assert(tree[v].chd[0] == x); 76 tree[v].chd[0] = 0; 77 } 78 return ans; 79 } 80 int main() { 81 tree[0] = node(0); 82 while(~scanf("%d",&n) && n) { 83 for(int i=0;i<n;i++) { 84 scanf("%d",&num[i].v); 85 insert(i+1); 86 num[i].id = i; 87 } 88 sort(num,num+n); 89 for(int i=0;i<n;i++) { 90 int pos = num[i].id + 1; 91 int ans = cal(pos) + i; 92 if(i) putchar(' '); 93 printf("%d",ans); 94 } 95 puts(""); 96 } 97 return 0; 98 }