RE:从零开始的数据结构生活 第二弹
继昨天RE:从零开始的数据结构生活之后,我陷入splay中不能自拔,所以说今天又学了下splay的区间(翻转)操作。
不得不说,一颗赛艇~
每当要翻转区间[l,r]时,先将l-1转到根的位置,再把r+1转到根的位置,则根的左子树就是要翻转的区间,然后交换左右儿子的指针就好了
以BZOJ 3223为例题, 贴一份模板
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int SZ = 1e6 + 10;
const int INF = 1e9;
struct node
{
node *ch[2], *f;
int v, sz, cnt;
bool flag;
void maintain()
{
sz = cnt + ch[1] -> sz + ch[0] -> sz;
}
int cmp(int x)
{
if(x == v) return -1;
return x < v ? 0 : 1;
}
int dir()
{
return f -> ch[1] == this;
}
void setc(node *x, int d)
{
(ch[d] = x) -> f = this;
}
void pushdown();
}T[SZ], *root, *null;
int Tcnt, n, m;
void node :: pushdown()
{
if(flag)
{
flag = 0;
if(ch[1] != null) ch[1] -> flag ^= 1;
if(ch[0] != null) ch[0] -> flag ^= 1;
swap(ch[0], ch[1]);
}
}
node *newnode(int x, node *f)
{
node *k = T + (++Tcnt);
k -> sz = k -> cnt = 1;
k -> v = x;
k -> ch[0] = k -> ch[1] = null;
k -> flag = 0;
k -> f = f;
return k;
}
void rotate(node *p)
{
p -> f -> pushdown();
p -> pushdown();
node *fa = p -> f;
int d = p -> dir();
fa -> f -> setc(p, fa -> dir());
fa -> setc(p -> ch[d ^ 1], d);
fa -> maintain();
p -> setc(fa, d ^ 1);
p -> maintain();
if(fa == root) root = p;
}
void splay(node *p, node *rt = null)
{
while(p -> f != rt)
{
p -> pushdown();
if(p -> f -> f == rt) rotate(p);
else
{
if(p -> dir() == p -> f -> dir()) rotate(p -> f), rotate(p);
else rotate(p), rotate(p);
}
}
}
node* find(node *p, int k)
{
while(p != null)
{
p -> pushdown();
int l = p -> ch[0] -> sz + 1;
int r = p -> ch[0] -> sz + p -> cnt;
if(l <= k && k <= r) return p;
if(k > r) k -= r, p = p -> ch[1];
else p = p -> ch[0];
}
}
void reverse(node *p, int l, int r)
{
l++; r++;
node *pre = find(root, l - 1);
node *suf = find(root, r + 1);
splay(pre);
splay(suf, root);
root -> ch[1] -> ch[0] -> flag ^= 1;
}
void build(node* &p, int l, int r, node *fa) //将1-n插入到splay中
{
if(l > r) return;
int mid = (l + r) >> 1;
p = newnode(mid, fa);
build(p -> ch[0], l, mid - 1, p);
build(p -> ch[1], mid + 1, r, p);
p -> maintain();
}
void init()
{
null = newnode(-INF, null);
null -> sz = null -> cnt = 0;
root = newnode(-INF, null);
root -> ch[1] = newnode(INF, root);
build(root -> ch[1] -> ch[0], 1, n, root -> ch[1]);
root -> ch[1] -> maintain();
root -> maintain();
}
int main()
{
scanf("%d%d", &n, &m);
init();
int l, r;
while(m--)
{
scanf("%d%d", &l, &r);
reverse(root, l, r);
}
for(int i = 1; i <= n; i++)
printf("%d ", (find(root, i + 1)) -> v);
return 0;
}