题目描述:
题解:
首先为了方便1~n的翻转,在区间左右加两个哨兵下标分别为1和n + 2,值分别为-INF和INF,然后中序建树,根节点为(1 + n + 2) >> 1,由于在区间中找的数是从小到大排列,所以可以对输入数据进行排序,用一个结构体让下标也跟着被排序(每个数的下标也是在Splay树中的下标),然后遍历排序后的数组,每次将该值的下标旋转到根,根左子树的大小即为答案ans,然后找到应该翻转的区间:左边界为区间第 L = i 个值 (i从2开始,i = 1为哨兵),右边界为第R = ans + 1个(ans为根的左子树大小,而翻转的区间包括根节点,所以+1),然后Reverse(L - 1, R + 1),本题还有一点是在Splay时要进行push_down。
AC代码
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <deque>
#include <list>
#include <iomanip>
#include <algorithm>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
//#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
//cout << fixed << setprecision(2);
//cout << setw(2);
const int N = 1e5 + 5, M = 1e9 + 7;
const int INF = 0x3f3f3f3f;
struct Node {
int l, r, sz, fa, rev, v;
}h[N];
int root;
int n, ans[N], cnt;
pair<int, int> Data[N];
void update(int x) {
h[x].sz = h[h[x].l].sz + h[h[x].r].sz + 1;
}
void push_down(int x) {
if (h[x].rev) {
swap(h[x].l, h[x].r);
h[h[x].l].rev ^= 1;
h[h[x].r].rev ^= 1;
h[x].rev = 0;
}
}
int Build(int l, int r, int fa) {
if (l > r) return 0;
int mid = (l + r) >> 1;
h[mid].fa = fa, h[mid].sz = 1;
h[mid].l = Build(l, mid - 1, mid);
h[mid].r = Build(mid + 1, r, mid);
update(mid);
return mid;
}
void Zig(int x) {
int y = h[x].fa, z = h[y].fa;
if (h[z].l == y) h[z].l = x;
if (h[z].r == y) h[z].r = x;
h[x].fa = z, h[y].fa = x;
h[y].l = h[x].r, h[h[x].r].fa = y, h[x].r = y;
update(y), update(x);
}
void Zag(int x) {
int y = h[x].fa, z = h[y].fa;
if (h[z].l == y) h[z].l = x;
if (h[z].r == y) h[z].r = x;
h[x].fa = z, h[y].fa = x;
h[y].r = h[x].l, h[h[x].l].fa = y, h[x].l = y;
update(y), update(x);
}
void Splay(int x, int fa) {
while (h[x].fa != fa) {
int y = h[x].fa, z = h[y].fa;
push_down(z), push_down(y), push_down(x);
if (h[z].l == y && h[y].l == x && z != fa) {
Zig(y), Zig(x);
} else if (h[y].l == x) {
Zig(x);
} else if (h[z].r == y && h[y].r == x && z != fa) {
Zag(y), Zag(x);
} else {
Zag(x);
}
}
if (!fa) root = x;
}
int Kth(int k) {
int z = root;
while (1) {
push_down(z);
int cnt = h[h[z].l].sz + 1;
if (k < cnt) {
z = h[z].l;
} else if (k > cnt) {
k -= cnt;
z = h[z].r;
} else {
return z;
}
}
}
// void In(int x) {
// push_down(x);
// if (h[x].l) In(h[x].l);
// cout << x << " ";
// if (h[x].r) In(h[x].r);
// }
int main() {
//freopen("/Users/xumingfei/Desktop/ACM/test.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
Data[1].first = -INF, Data[1].second = 1;
Data[n + 2].first = INF, Data[n + 2].second = n + 2;
for (int i = 2; i <= n + 1; i++) {
cin >> Data[i].first;
Data[i].second = i;
}
root = (1 + n + 2) >> 1;
Build(1, n + 2, 0);
sort(Data + 1, Data + n + 2 + 1);
for (int i = 2; i <= n + 1; i++) {
Splay(Data[i].second, 0);
int ans = h[h[root].l].sz;
cout << ans << ' ';
int l = Kth(i - 1), r = Kth(ans + 2);
Splay(l, 0), Splay(r, l);
h[h[r].l].rev ^= 1;
}
cout << '\n';
return 0;
}