P3391 【模板】文艺平衡树

知识点: 平衡树

原题面

题目要求

维护一数列,序列中第 \(i\) 项初始为 \(i\)
支持区间翻转操作,输出多次翻转后的序列。

分析题意

使被操作序列置于一棵完整的子树中。
通过在 子树根打标记实现区间操作。
Splay 和 Treap 将序列旋转至一棵子树中,
Fhq-Treap 将序列分裂至一棵子树中。


代码实现

Splay

//Splay
#include <cstdio>
#include <ctype.h>
#include <algorithm>
#define min std::min
#define max std::max
#define ll long long
#define Fat (t[now].Fa)
#define ls (t[now].Son[0])
#define rs (t[now].Son[1])
const int MARX = 1e6 + 10;
const int INF = 1e9 + 2077;
//=============================================================
struct SplayNode
{
	int Fa, Son[2];
	int Val, Size, Cnt;
	bool tag;
} t[MARX];
int N, M, NodeNum, Root;
//=============================================================
inline int read()
{
	int f = 1, w = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
	return f * w;
}
bool GetSonNum(int now) {return t[Fat].Son[1] == now;}
int NewNode(int Fa, int Val)
{
	++ NodeNum;
	t[NodeNum].Cnt = t[NodeNum].Size = 1, t[NodeNum].Fa = Fa, t[NodeNum].Val = Val;
	if(Val == 0 || Val == N + 1) t[NodeNum].Val = Val ? - INF : INF;
	return NodeNum;
}
void Pushup(int now)
{
	if(! now) return ;
	t[now].Size = t[now].Cnt;
	if(ls) t[now].Size += t[ls].Size;
	if(rs) t[now].Size += t[rs].Size;
}
void Pushdown(int now)
{
	if(! now || ! t[now].tag) return ;
	t[t[now].Son[0]].tag ^= 1, t[t[now].Son[1]].tag ^= 1;
	std :: swap(t[now].Son[0], t[now].Son[1]);
	t[now].tag = 0;
}
void Rotate(int now)
{
	int fa = Fat, gfa = t[fa].Fa, WhichSon = GetSonNum(now);
	t[fa].Son[WhichSon] = t[now].Son[WhichSon ^ 1];
	t[t[fa].Son[WhichSon]].Fa = fa;
	
	t[now].Son[WhichSon ^ 1] = fa; t[fa].Fa = now;
	
	t[now].Fa = gfa;
	if(gfa) t[gfa].Son[t[gfa].Son[1] == fa] = now;
	Pushup(fa), Pushup(now);
}
void Splay(int now, int Target)
{
	for(int fa = Fat; (fa = Fat) != Target; Rotate(now))
	  if(t[fa].Fa != Target) Rotate(GetSonNum(now) == GetSonNum(fa) ? fa : now);
	if(! Target) Root = now;
}
int Kth(int now, int Size)
{
	while(1)
	{
	  Pushdown(now);
	  if(Size <= t[t[now].Son[0]].Size) {now = t[now].Son[0]; continue;}
	  if(Size == t[t[now].Son[0]].Size + 1) return now;
	  Size -= t[t[now].Son[0]].Size + 1, now = t[now].Son[1];
	}
}
void Reverse(int L, int R)
{
	L = Kth(Root, L), 
	R = Kth(Root, R);
	Splay(L, 0), 
	Splay(R, L);
	t[t[t[Root].Son[1]].Son[0]].tag ^= 1;
}
int Build(int fa, int L, int R)
{
	if(L > R) return 0;
	int mid = (L + R) >> 1, now = NewNode(fa, mid);
	t[now].Son[0] = Build(now, L, mid - 1);
	t[now].Son[1] = Build(now, mid + 1, R);
	Pushup(now); 
	return now;
}
void Print(int now)
{
	if(! now) return ;
	Pushdown(now);
	Print(t[now].Son[0]);
	if(t[now].Val >= 1 && t[now].Val <= N) printf("%d ", t[now].Val);
	Print(t[now].Son[1]);
}
//=============================================================
int main()
{
	N = read(), M = read();
	Root = Build(0, 0, N + 1);
	for(int i = 1; i <= M; i ++)
	{
	  int L = read(), R = read();
	  Reverse(L, R + 2);
	}
	Print(Root);
	return 0;
}

Fhq-Treap

/*
By:Luckyblock
FHQ-treap 
*/
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <ctype.h>
#define min std::min
#define max std::max
#define ll long long
const int MARX = 1e5 + 10; 
//============================================================= 
struct FhqTreapNode
{
	int son[2], val, Rand, size;
	bool tag;
} t[MARX];
int N, M, NodeNum, Root;
//=============================================================
inline int read()
{
	int f = 1, w = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
	return f * w;
}
void Update(int x) 
{
	t[x].size = t[t[x].son[0]].size + t[t[x].son[1]].size + 1;
	if(! x || ! t[x].tag) return ;
	t[x].tag ^= 1;
	std :: swap(t[x].son[0], t[x].son[1]);
	t[t[x].son[0]].tag ^= 1, t[t[x].son[1]].tag ^= 1;
	
}
int NewNode(int Val)
{
	NodeNum ++;
	t[NodeNum] = (FhqTreapNode) {0, 0, Val, rand(), 1, 0};
//	t[NodeNum].size = 1; t[NodeNum].val = Val; t[NodeNum].Rand = rand();
	return NodeNum;
}
int Build(int L, int R)
{
	if(L > R) return 0;
	int mid = (L + R) >> 1, Val = mid - 1;
	int now = NewNode(Val);
	t[now].son[0] = Build(L, mid - 1);
	t[now].son[1] = Build(mid + 1, R);
	Update(now);
	return now;
}
int Merge(int x, int y)
{
	if(! x || ! y) return x + y;
	Update(x), Update(y);
	if(t[x].Rand < t[y].Rand)
	{
	  t[x].son[1] = Merge(t[x].son[1], y); 
	  Update(x);
	  return x;
	}
	t[y].son[0] = Merge(x, t[y].son[0]); 
	Update(y);
	return y;
}
void Split(int now, int Key, int &x, int &y)
{
	if(! now) {x = y = 0; return ;}
	Update(now);
	if(Key <= t[t[now].son[0]].size) y = now, Split(t[now].son[0], Key, x, t[y].son[0]);
	else x = now, Split(t[now].son[1], Key - t[t[now].son[0]].size - 1, t[x].son[1], y);
	Update(now);
}
void Reverse(int L, int R)
{
	int tmp1, tmp2, tmp3, tmp4;
	Split(Root, R + 1, tmp1, tmp2), Split(tmp1, L, tmp3, tmp4);
	t[tmp4].tag ^= 1; Root = Merge(Merge(tmp3, tmp4), tmp2);
}
void Print(int x)
{
	if(! x) return ;
	Update(x);
	Print(t[x].son[0]);
	if(t[x].val >= 1 && t[x].val <= N) printf("%d ", t[x].val);
	Print(t[x].son[1]);
}
//=============================================================
int main()
{
	srand(time(0));
	N = read(), M = read();
	Root = Build(1, N + 2);
	for(int i = 1, L, R; i <= M; i ++) L = read(), R = read(), Reverse(L, R);
	Print(Root);
	return 0;
}
posted @ 2020-05-23 11:36  Luckyblock  阅读(255)  评论(1编辑  收藏  举报