【模板】文艺平衡树

题目

(m) 次区间翻转操作,(1 leq n,m leq 100000)

分析

平衡树模板
于是放上 (fhq-treap) 的板子

(Code)

#include<cstdio>
#include<algorithm>
#include<ctime>
using namespace std;

const int N = 1e5 + 5;
int n, m, rt;

struct node{
	int ls, rs, val, rnd, tag, siz;
}tr[N];

void read(int &x)
{
	x = 0; char ch = getchar();
	while (ch < '0' || ch > '9') ch = getchar();
	while (ch >= '0' && ch <= '9')
		x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
}

void update(int p){tr[p].siz = tr[tr[p].ls].siz + tr[tr[p].rs].siz + 1;}

int new_node(int v)
{
	static int tot = 0;
	tr[++tot] = node{0, 0, v, rand(), 0, 1};
	return tot;
}

int build(int l, int r)
{
	if (l > r) return 0; 
	int mid = (l + r) >> 1, p = new_node(mid);
	tr[p].ls = build(l, mid - 1);
	tr[p].rs = build(mid + 1, r);
	update(p); return p;
}

void pushdown(int p)
{
	if (!p || !tr[p].tag) return;
	tr[p].tag = 0;
	swap(tr[p].ls, tr[p].rs);
	if (tr[p].ls) tr[tr[p].ls].tag ^= 1;
	if (tr[p].rs) tr[tr[p].rs].tag ^= 1;
}

void split(int p, int k, int &x, int &y)
{
	if (!p) x = y = 0;
	else{
		pushdown(p);
		if (k <= tr[tr[p].ls].siz)
			y = p, split(tr[p].ls, k, x, tr[p].ls);
		else x = p, split(tr[p].rs, k - tr[tr[p].ls].siz - 1, tr[p].rs, y);
		update(p);
	}
}

int merge(int x, int y)
{
	if (!x || !y) return x + y;
	pushdown(x), pushdown(y);
	if (tr[x].rnd < tr[y].rnd)
	{
		tr[x].rs = merge(tr[x].rs, y);
		update(x); return x;
	}
	else{
		tr[y].ls = merge(x, tr[y].ls);
		update(y); return y;
	}
}

void dfs(int p)
{
	if (!p) return;
	pushdown(p); 
	dfs(tr[p].ls); 
	printf("%d ", tr[p].val);
	dfs(tr[p].rs);
}

void reverse(int l, int r)
{
	int a, b, c, d;
	split(rt, r, a, b), split(a, l - 1, c, d);
	tr[d].tag ^= 1 , rt = merge(merge(c, d), b);
}

int main()
{
	srand(time(0));
	read(n), read(m);
	rt = build(1, n);
	for(register int i = 1, l, r; i <= m; i++)
		read(l), read(r), reverse(l, r);
	dfs(rt);
}
原文地址:https://www.cnblogs.com/leiyuanze/p/14060658.html