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 }

 

 posted on 2013-08-12 13:35  tobec  阅读(232)  评论(0编辑  收藏  举报