题目背景
这是一道经典的Splay模板题——文艺平衡树。
题目描述
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
输入输出格式
输入格式:
第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2,⋯n−1,n) m表示翻转操作次数
接下来m行每行两个数 [l,r][l,r] 数据保证 n1≤l≤r≤n
输出格式:
输出一行n个数字,表示原始序列经过m次变换后的结果
输入输出样例
输入样例#1:
5 3 1 3 1 3 1 4输出样例#1:
4 3 2 1 5说明
n,m≤100000
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>
#ifdef ONLINE_JUDGE
#define debug
#else
#define debug printf("passing [%s] in line %d\n", __FUNCTION__, __LINE__)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> p;
const int N = 100010;
int val[N], tag[N], ch[N][2], sz[N], tot;
int nn(int v) {
++ tot;
tot[val] = v;
tot[sz] = 1;
return tot;
}
void push(int x) {
if(tag[x]) {
swap(x[ch][0], x[ch][1]);
x[ch][0][tag] ^= 1;
x[ch][1][tag] ^= 1;
x[tag] = 0;
}
}
void update(int x) {
x[sz] = x[ch][0][sz] + x[ch][1][sz] + 1;
}
int merge(int a, int b) {
push(a), push(b);
if(!a || !b) return a | b;
if(rand() % (a[sz] + b[sz]) < a[sz]) {
a[ch][1] = merge(a[ch][1], b);
update(a);
return a;
} else {
b[ch][0] = merge(a, b[ch][0]);
update(b);
return b;
}
}
p split(int x, int k) {
push(x);
p ret = p(0, 0);
if(x) {
if(x[ch][0][sz] >= k) {
ret = split(x[ch][0], k);
x[ch][0] = ret.second;
ret.second = x;
} else {
ret = split(x[ch][1], k - x[ch][0][sz] - 1);
x[ch][1] = ret.first;
ret.first = x;
}
update(x);
}
return ret;
}
int n, m, rt;
void dfs(int x) {
push(x);
if(x) {
dfs(x[ch][0]);
printf("%d ", x[val]);
dfs(x[ch][1]);
}
}
int main() {
srand((unsigned long long) new char);
scanf("%d%d", &n, &m);
for(int i = 1 ; i <= n ; ++ i) {
rt = merge(rt, nn(i));
}
for(int i = 1, l, r ; i <= m ; ++ i) {
scanf("%d%d", &l, &r);
p p1 = split(rt, r);
p p2 = split(p1.first, l - 1);
p2.second[tag] ^= 1;
rt = merge(merge(p2.first, p2.second), p1.second);
}
dfs(rt);
}