【题目链接】
【双倍经验链接】
【思路要点】
- 将权值当做下标,我们需要实现的是查询一个节点在数组中的排名,以及翻转数组的一个区间。
- 用Splay维护即可,时间复杂度 。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
write(x);
puts("");
}
struct Splay {
struct Node {
int child[2];
int father;
int size;
bool rev;
} a[MAXN];
int root, n;
void update(int root) {
a[root].size = 1;
if (a[root].child[0]) a[root].size += a[a[root].child[0]].size;
if (a[root].child[1]) a[root].size += a[a[root].child[1]].size;
}
void build(int &root, int l, int r, int *pos) {
int mid = (l + r) / 2;
root = pos[mid];
if (l < mid) {
build(a[root].child[0], l, mid - 1, pos);
a[a[root].child[0]].father = root;
}
if (mid < r) {
build(a[root].child[1], mid + 1, r, pos);
a[a[root].child[1]].father = root;
}
update(root);
}
void init(int x, int *a) {
n = x;
a[0] = n + 1;
a[n + 1] = n + 2;
build(root, 0, n + 1, a);
}
void pushdown(int root) {
if (a[root].rev) {
a[root].rev = false;
swap(a[root].child[0], a[root].child[1]);
if (a[root].child[0]) a[a[root].child[0]].rev ^= true;
if (a[root].child[1]) a[a[root].child[1]].rev ^= true;
}
}
bool get(int x) {
return a[a[x].father].child[1] == x;
}
void rotate(int x) {
int f = a[x].father, g = a[f].father;
pushdown(f), pushdown(x);
bool tmp = get(x);
a[f].child[tmp] = a[x].child[tmp ^ 1];
if (a[f].child[tmp]) a[a[f].child[tmp]].father = f;
a[x].child[tmp ^ 1] = f;
a[f].father = x;
a[x].father = g;
if (g) a[g].child[a[g].child[1] == f] = x;
update(f), update(x);
}
void splay(int x) {
pushdown(x);
for (int f = a[x].father; (f = a[x].father) != 0; rotate(x))
if (a[f].father != 0) {
if (get(f) == get(x)) rotate(f);
else rotate(x);
}
root = x;
}
void spaly(int x) {
pushdown(x);
for (int f = a[x].father; (f = a[x].father) != root; rotate(x))
if (a[f].father != root) {
if (get(f) == get(x)) rotate(f);
else rotate(x);
}
}
int succ() {
int now = a[root].child[1];
pushdown(now);
while (a[now].child[0]) {
now = a[now].child[0];
pushdown(now);
}
return now;
}
void work() {
for (int i = 1; i <= n; i++) {
splay(i);
printf("%d", a[a[root].child[0]].size);
if (i == n) putchar('\n');
else putchar(' ');
int tmp = succ();
if (i == 1) splay(n + 1);
else splay(i - 1);
spaly(tmp);
a[a[a[root].child[1]].child[0]].rev ^= true;
}
}
} Splay;
int n, val[MAXN], p[MAXN];
bool cmp(int x, int y) {
if (val[x] == val[y]) return x < y;
else return val[x] < val[y];
}
int main() {
read(n);
for (int i = 1; i <= n; i++)
read(val[i]), p[i] = i;
sort(p + 1, p + n + 1, cmp);
for (int i = 1; i <= n; i++)
val[p[i]] = i;
Splay.init(n, val);
Splay.work();
return 0;
}