P3391 【模板】文艺平衡树

模板题 link

Splay 区间翻转,存个代码

旋转时,要注意goal是引用 , 并记得修改 , 有标记的一定记得标记下放 , 还有清空

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 101000;
inline int read()
{
	register int x = 0 , f = 0; register char c = getchar();
	while(c < '0' || c > '9') f |= c == '-' , c = getchar();
	while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
	return f ? -x : x;
}
#define RQ puts("RQ");
int n , m , sz , root;
int tr[N][2] , val[N] , rev[N] , fa[N] , siz[N];
inline int Newnode() { return ++sz; }
inline void update(int x) { siz[x] = siz[tr[x][0]] + siz[tr[x][1]] + 1; }
inline int witch(int x) { return x == tr[fa[x]][1]; }
inline int rk(int x) { return 1 + siz[tr[x][0]]; }
void rot(int x , int &goal) // 忘记了修改 goal 
{
	int y = fa[x] , z = fa[y] , k = witch(x) , w = tr[x][!k];
	if(y == goal) goal = x; else tr[z][witch(y)] = x; 
	fa[x] = z; tr[y][k] = w; if(w) fa[w] = y;
	tr[x][!k] = y; fa[y] = x;
	update(y); update(x);
}

void down(int x)
{
	if(!x || !rev[x]) return ; // 没用判断标记 
	swap(tr[x][0] , tr[x][1]);
	if(tr[x][0]) rev[tr[x][0]] ^= 1;
	if(tr[x][1]) rev[tr[x][1]] ^= 1;
	rev[x] = 0; // 还没有清空 
	return ;
}

void Splay(int x , int &goal) // 引用 
{
	while(x != goal)
	{
		if(fa[x] != goal) rot(witch(x) == witch(fa[x]) ? fa[x] : x , goal);
		rot(x , goal);
	}
	return ;
}

void build(int &k , int l , int r , int f)
{
	if(l > r) return ; int mid = (l + r) >> 1;
	if(!k) k = Newnode(); siz[k] = 1; fa[k] = f; val[k] = mid;
	build(tr[k][0] , l , mid - 1 , k);
	build(tr[k][1] , mid + 1 , r , k);
	update(k); return ;
}

int kth(int k) // 求的是第k大的是谁 , 而不是k的排名 
{
	int p = root;
	while(down(p) , rk(p) != k)
	{
		if(rk(p) < k) k -= rk(p) , p = tr[p][1];
		else p = tr[p][0];
	}
	Splay(p , root);
	return p;
}

void reverse(int l , int r)
{
	int x = kth(l) , y = kth(r);
	Splay(x , root); Splay(y , tr[x][1]);
	rev[tr[y][0]] ^= 1; return ;
}

void dfs(int x)
{
	if(!x) return ; down(x);
	dfs(tr[x][0]);
	if(val[x] >= 1 && val[x] <= n) printf("%d " , val[x]);
	dfs(tr[x][1]);
	return ;
}

int main()
{
	n = read(); m = read();
	build(root , 0 , n+1 , 0);
	for(int i = 1 ; i <= m ; ++i)
	{
		int l = read() , r = read();
		reverse(l , r + 2);
	}
	dfs(root);
	return 0;
}