文艺平衡树
题目链接:luogu P3391
题目大意
给一个数列,会有一些操作,把里面的一个区间翻转。
要你输出最后数列的样子。
思路
只是练练无旋 Treap 罢了。
就打个懒标记。
然后最后中序遍历过去就好了。
一定要记得 u p , d o w n up,down up,down!
代码
#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
int val[100001], ls[100001], rs[100001], turn[100001], yj[100001];
int size[100001];
int n, m, a[100001], x, y;
int sta[100001], tot, root;
int get_new(int num) {
int now = ++tot;
ls[now] = rs[now] = 0;
turn[now] = 0;
yj[now] = rand();
val[now] = num;
size[now] = 1;
return now;
}
void up(int now) {
size[now] = size[ls[now]] + size[rs[now]] + 1;
}
void turn_down(int now) {
swap(ls[now], rs[now]);
turn[now] ^= 1;
}
void down(int now) {
if (turn[now]) {
if (ls[now]) turn_down(ls[now]);
if (rs[now]) turn_down(rs[now]);
turn[now] ^= 1;
}
}
int build(int tot) {
int now = get_new(a[1]);
sta[++sta[0]] = now;
for (int i = 2; i <= tot; i++) {
now = get_new(a[i]);
int lst = 0;
while (sta[0] && yj[sta[sta[0]]] > yj[now]) {
up(sta[sta[0]]);
lst = sta[sta[0]];
sta[sta[0]--] = 0;
}
ls[now] = lst;
up(now);
if (sta[0]) {
rs[sta[sta[0]]] = now;
up(sta[sta[0]]);
}
sta[++sta[0]] = now;
}
int lst = sta[sta[0]];
while (sta[0]) {
up(sta[sta[0]]);
lst = sta[sta[0]];
sta[sta[0]--] = 0;
}
return lst;
}
pair <int, int> split_rnk(int now, int rnk) {
if (!now) return make_pair(0, 0);
if (!rnk) return make_pair(0, now);
pair <int, int> re;
down(now);
if (size[ls[now]] >= rnk) {
re = split_rnk(ls[now], rnk);
ls[now] = re.second;
up(now);
re.second = now;
}
else {
re = split_rnk(rs[now], rnk - size[ls[now]] - 1);
rs[now] = re.first;
up(now);
re.first = now;
}
return re;
}
int merge(int x, int y) {
if (x) down(x);
if (y) down(y);
if (!x) return y;
if (!y) return x;
if (yj[x] < yj[y]) {
rs[x] = merge(rs[x], y);
up(x);
return x;
}
else {
ls[y] = merge(x, ls[y]);
up(y);
return y;
}
}
void change_(int s, int t) {
pair <int, int> x = split_rnk(root, s - 1);
pair <int, int> y = split_rnk(x.second, t - s + 1);
turn[y.first] ^= 1;
swap(ls[y.first], rs[y.first]);
root = merge(x.first, merge(y.first, y.second));
}
void write(int now) {
down(now);
if (ls[now]) write(ls[now]);
printf("%d ", val[now]);
if (rs[now]) write(rs[now]);
}
int main() {
srand(19491001);
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
a[i] = i;
root = build(n);
while (m--) {
scanf("%d %d", &x, &y);
change_(x, y);
}
write(root);
return 0;
}