BZOJ1552【CERC2007】Robotic Sort < Splay >

Problem

【CERC2007】Robotic Sort

Time  Limit:  5  Sec\mathrm{Time\;Limit:\;5\;Sec}
Memory  Limit:  64  MB\mathrm{Memory\;Limit:\;64\;MB}

Description

Input

输入共两行,第一行为一个整数NNNN表示物品的个数,1N1051\le N\le10^5
第二行为NN个用空格隔开的正整数,表示NN个物品最初排列的编号。

Output

输出共一行,NN个用空格隔开的正整数P1,P2,P3PnP_1,P_2,P_3\cdots P_nPiP_i表示第ii次操作前第ii小的物品所在的位置。
注意:如果第ii次操作前,第ii小的物品己经在正确的位置PiP_i上,我们将区间[Pi,Pi][P_i,P_i]反转(单个物品)。

Sample Input

1
2
6
3 4 5 1 6 2

Sample Output

1
4 6 4 5 6 6

标签:Splay

Solution

Splay\mathrm{Splay}基础题。

将所有物品按照位置从小到大插入Splay\mathrm{Splay}中,并维护每个结点及其子树中的最小值和最小值所在的结点指针。对于第ii次操作,在区间[i,n][i,n]找出最小值所在的结点指针,查询其位置是多少,令其为pp,输出后反转区间[i,p][i,p]即可。

注意这道题的物品大小有重复,需要先按照大小为第一关键字,位置为第二关键字离散化后再开始操作。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <bits/stdc++.h>
#define MAX_N 100000
#define INF 0x3f3f3f3f
#define flag cur->fa->fa!=tar&&cur->fa->fa->s[sn]==cur->fa
using namespace std;
template <class T> inline void read(T &x) {
x = 0; int c = getchar(), f = 1;
for (; !isdigit(c); c = getchar()) if (c == 45) f = -1;
for (; isdigit(c); c = getchar()) (x *= 10) += f*(c-'0');
}
int n, a[MAX_N+5];
struct data {int c, p;} seq[MAX_N+5];
bool cmp(const data &x, const data &y) {
return x.c == y.c ? x.p < y.p : x.c < y.c;
}
struct SplayNode {
SplayNode *s[2], *fa, *p; int c, mi, sz; bool rev;
void update() {
p = this, mi = c;
sz = (s[0]?s[0]->sz:0)+(s[1]?s[1]->sz:0)+1;
if (s[0] && s[0]->mi < mi) mi = s[0]->mi, p = s[0]->p;
if (s[1] && s[1]->mi < mi) mi = s[1]->mi, p = s[1]->p;
}
void downtag() {
if (!rev) return; rev = false, swap(s[0], s[1]);
if (s[0]) s[0]->rev ^= 1; if (s[1]) s[1]->rev ^= 1;
}
} ;
struct SplayTree {
SplayNode* rt;
SplayNode* newnode(int x) {
SplayNode* v = new SplayNode;
v->s[0] = v->s[1] = v->fa = NULL, v->p = v;
v->c = v->mi = x, v->sz = 1, v->rev = false;
return v;
}
SplayTree() {
rt = newnode(-INF), rt->s[1] = newnode(INF);
rt->s[1]->fa = rt, rt->update();
}
void pushdown(SplayNode* cur) {
if (!cur) return;
pushdown(cur->fa);
cur->downtag();
}
void rotate(SplayNode* v, bool sn) {
SplayNode* f = v->fa;
f->s[sn^1] = v->s[sn], v->fa = f->fa;
if (f->s[sn^1]) f->s[sn^1]->fa = f;
if (v->fa) v->fa->s[f == f->fa->s[1]] = v;
v->s[sn] = f, f->fa = v, f->update(), v->update();
}
void splay(SplayNode* cur, SplayNode* tar) {
pushdown(cur);
while (cur != tar && cur->fa != tar) {
bool sn = cur->fa->s[1] == cur;
if (flag) rotate(cur->fa, sn^1);
rotate(cur, sn^1);
}
if (cur->fa == tar) rotate(cur, cur->fa->s[0] == cur);
if (tar == rt) rt = cur;
}
SplayNode* get_kth(SplayNode* v, int k) {
v->downtag();
int lsz = v->s[0] ? v->s[0]->sz : 0;
if (k <= lsz) return get_kth(v->s[0], k);
if (k > lsz+1) return get_kth(v->s[1], k-lsz-1);
return v;
}
void insert(int p, int x) {
SplayNode* pre = get_kth(rt, p+1);
SplayNode* suc = get_kth(rt, p+2);
splay(pre, rt), splay(suc, rt->s[1]);
suc->s[0] = newnode(x), suc->s[0]->fa = suc;
suc->update(), rt->update();
}
void reverse(int l, int r) {
SplayNode* pre = get_kth(rt, l);
SplayNode* suc = get_kth(rt, r+2);
splay(pre, rt), splay(suc, rt->s[1]);
suc->s[0]->rev ^= 1;
}
SplayNode* get_mi(int l, int r) {
SplayNode* pre = get_kth(rt, l);
SplayNode* suc = get_kth(rt, r+2);
splay(pre, rt), splay(suc, rt->s[1]);
return suc->s[0]->p;
}
int get_rank(SplayNode* v) {
splay(v, rt);
return rt->s[0]->sz;
}
} BBST;
int main() {
read(n);
for (int i = 1; i <= n; i++)
read(seq[i].c), seq[i].p = i;
sort(seq+1, seq+n+1, cmp);
for (int i = 1; i <= n; i++)
a[seq[i].p] = i;
for (int i = 1; i <= n; i++)
BBST.insert(i-1, a[i]);
for (int i = 1; i <= n; i++) {
int p = BBST.get_rank(BBST.get_mi(i, n));
printf("%d ", p), BBST.reverse(i, p);
}
return 0;
}