题意:
操作1:将区间[a,b]切下来放到c位置后面。
操作2:将区间[a,b]翻转。
输出最后的数列。
思路 :
显然Splay。
翻转就是加一个 翻转标记即可。正常操作。
简单说一下 切割区间。
先把a-1 转到根, 在把b+1 转到根的下面, 将根右儿子的左儿子切下来(保证子树是区间[a,b])
pushup一下
在把c转到根, c + 1 转到根的下面, 根右儿子 左儿子 一定是空的, 插进去即可。
#include
#include
#include
using namespace std;
const int maxn = 300000 + 10;
int n, m;
int ks = 0;
int num[maxn];
const int inf = 0x3f3f3f3f;
struct SplayTree{
void Rotate(int x, int f){
int y = pre[x], z = pre[y];
pushdown(x);
pushdown(y);
ch[y][!f] = ch[x][f]; pre[ch[x][f] ] = y;
ch[x][f] = y; pre[y] = x;
pre[x] = z;
if (pre[x]) ch[z][ch[z][1] == y ] = x;
pushup(y);
}
void Splay(int x,int goal){
pushdown(x);
while(pre[x] != goal){
if (pre[pre[x] ] == goal){
Rotate(x, ch[pre[x] ][0] == x);
}
else {
int y = pre[x], z = pre[y];
int f = (ch[z][0] == y);
if (ch[y][f] == x) Rotate(x, !f), Rotate(x, f);
else Rotate(y, f), Rotate(x, f);
}
}
pushup(x);
if (goal == 0) root = x;
}
void RotateTo(int k,int goal){
int x = root;
pushdown(x);
while(sz[ ch[x][0] ] != k){
if (k < sz[ ch[x][0] ]){
x = ch[x][0];
}
else {
k -= (sz[ ch[x][0] ] + 1);
x = ch[x][1];
}
pushdown(x);
}
Splay(x, goal);
}
void clear(){
ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
root = n = 0;
val[0] = -inf;
sum[0] = 0;
NewNode(root, -inf);
NewNode(ch[root][1], -inf);
pre[n] = root;
sz[root] = 2;
}
void NewNode(int& x,int c){
x = ++n;
ch[x][0] = ch[x][1] = pre[x] = 0;
sz[x] = 1;
val[x] = sum[x] = c;
lazy[x] = 0;
}
void pushup(int x){
sz[x] = 1 + sz[ch[x][0] ] + sz[ch[x][1] ];
sum[x] = val[x] + (sum[ch[x][0] ] + sum[ch[x][1] ]);
}
void pushdown(int x){
if (lazy[x] != 0){
update_rev(ch[x][0]);
update_rev(ch[x][1]);
lazy[x] = 0;
}
}
void init(int pos, int tot){
clear();
cnt = tot;
RotateTo(pos, 0);
RotateTo(pos + 1, root);
build(ch[ ch[root][1] ][0], 1, tot, ch[root][1]);
pushup(ch[root][1]);
pushup(root);
}
void build(int& x,int l,int r,int f){
if (l > r) return ;
int mid = (l + r) >> 1;
NewNode(x, num[mid]);
build(ch[x][0],l, mid-1, x);
build(ch[x][1], mid+1, r, x);
pre[x] = f;
pushup(x);
}
void update_same(int x,int v){
if (!x) return;
val[x] += v;
sum[x] += 1LL * v * sz[x];
lazy[x] += v;
}
void change(int l,int r,int c){
RotateTo(l - 1, 0);
RotateTo(r + 1, root);
int key = ch[ch[root][1] ][0];
update_same(key, c);
pushup(ch[root][1]);
pushup(root);
}
long long getsum(int l,int r){
RotateTo(l-1,0);
RotateTo(r+1,root);
int key = ch[ch[root][1] ][0];
return sum[key];
}
void cut(int a,int b,int c){
RotateTo(a-1,0);
RotateTo(b+1,root);
int key = ch[ ch[root][1] ][ 0 ];
ch[ ch[root][1] ][0] = 0;
pre[key] = 0;
pushup(ch[root][1]);
pushup(root);
RotateTo(c, 0);
RotateTo(c + 1, root);
ch[ ch[root][1] ][0] = key;
pre[key] = ch[root][1];
pushup(ch[root][1]);
pushup(root);
}
void flip(int l,int r){
RotateTo(l-1,0);
RotateTo(r+1,root);
int key = ch[ ch[root][1] ][0];
update_rev(key);
}
void update_rev(int x){
if (!x) return ;
swap(ch[x][0], ch[x][1]);
lazy[x] ^= 1;
}
void dfs(int cur){
if (cur == 0) return;
pushdown(cur);
dfs(ch[cur][0]);
if (val[cur] > -inf){
if (ks ++) putchar(' ');
printf("%d", val[cur]);
}
dfs(ch[cur][1]);
}
void solve(){
dfs(root);
puts("");
}
int root, n, cnt, ct, top;
int ch[maxn][2];
int pre[maxn];
int sz[maxn];
int val[maxn];
int lazy[maxn];
long long sum[maxn];
int pool[maxn];
}spt;
int main(){
int n, m;
while(~scanf("%d %d",&n, &m)){
ks = 0;
if (n == -1 && m == -1) break;
for (int i = 1; i <= n; ++i){
num[i] = i;
}
char op[10];
spt.init(0, n);
while(m--){
scanf("%s", op);
if (op[0] == 'C'){
int x, y, z;
scanf("%d %d %d",&x, &y, &z);
spt.cut(x, y, z);
}
else {
int x, y;
scanf("%d %d",&x, &y);
spt.flip(x, y);
}
}
spt.solve();
}
return 0;
}