题意:
最基本的维护数列。
提取区间,懒惰标记。。
思路:
先推入0和n+1两个元素,以方便处理边界情况。
用到的基本操作:insert,select(选取kth,0-indexed),splay
1)提取区间[a, b]
splay a-1th 到根,splay b+1th 到根的右孩子,则 b+1th 的左子树对应该区间。
2)反转区间
先反转自己的标记,标记向下传递(访问之前)的时候,交换左右儿子指针,并反转儿子的标记
3)剪切-粘贴
先提取区间,然后 splay kth to root,then splay k+1th to right child of root,and paste the subtree to k+1th。这样就把目标区间插在了kth后面。
int n, m;
struct node {
node *ch[2], *p;
int key, sz, rev;
node (int x = 0, node *c = NULL):p(0), key(x), sz(1), rev(0){ch[0] = ch[1] = c;}
void sc( node * c, int d ) { // set child
ch[d] = c;c->p = this;
}
int which(node *x) {return ch[1] == x;}
};
class splay_tree {
private:
void upd( node *x ) {
x->sz = x->ch[0]->sz + x->ch[1]->sz + 1;
}
void rot( node *x ) {
node *y = x->p;
int d = y->which(x);
y->sc(x->ch[!d], d);
y->p->sc(x, y->p->which(y));
x->sc(y, !d);
upd(y);upd(x);
}
void splay( node *x, node *y ) {
while ( x->p != y ) {
if (x->p->p == y) rot(x);
else {
if (x->p->p->which(x->p) == x->p->which(x))
rot(x->p), rot(x);
else
rot(x), rot(x);
}
}
}
// select kth: k is 0-based
node* select(node* x, int k) {
int r;
//assert(0 <= k && k <= n+1);
for(;;) {
pd(x);
r = x->ch[0]->sz;
if (r == k) return x;
x = x->ch[k>r];
if (k>r) k -= r+1;
}
return x;
}
void in_order(node *x, int &cnt) {
if (x == null) return;
pd(x);
in_order(x->ch[0], cnt);
if ( 1 <= cnt && cnt <= n) {
printf("%d", x->key);
if (cnt == n) printf("\n");
else printf(" ");
}
++cnt;
in_order(x->ch[1], cnt);
}
// push down
void pd(node *x) {
if (x == null) return;
if (x->rev) {
swap(x->ch[0], x->ch[1]);
x->ch[0]->rev ^= 1;
x->ch[1]->rev ^= 1;
x->rev = 0;
}
}
public:
void insert(int key) {
node *z = root->ch[1], *p = root;
while (z != null) {
p = z;z = z->ch[key >= z->key];
}
z = new node(key, null);
p->sc(z, key >= p->key);
splay(z, root);
}
int select(int k) {
//if (root->ch[1]->sz < k) return back();
node * x = select(root->ch[1], k);
return x->key;
}
void reverse(int l, int r) {
node *x = select(root->ch[1], l-1),
*y = select(root->ch[1], r+1);
splay(x, root);
splay(y, root->ch[1]);
y->ch[0]->rev ^= 1;
}
void cut(int l, int r, int o) {
node *x = select(root->ch[1], l-1),
*y = select(root->ch[1], r+1);
splay(x, root);
splay(y, root->ch[1]);
// cut-down subtree
node *tmp = y->ch[0];
y->sc(null, 0);
upd(y);upd(x);
x = select(root->ch[1], o),
y = select(root->ch[1], o+1);
splay(x, root);
splay(y, root->ch[1]);
// paste subtree
y->sc(tmp, 0);
upd(y);upd(x);
}
void print_inOrder() {
int cnt = 0;
in_order(root->ch[1], cnt);
}
public:
splay_tree() {
null = new node();null->sz = 0;
root = new node(-inf, null);
}
~splay_tree() {destroy(root->ch[1]);delete root;delete null;}
void destroy(node *x) {
if (x == null) return;
destroy(x->ch[0]);destroy(x->ch[1]);
delete x;
}
public:
node *null;
node *root;
};