3223. 文艺平衡树【平衡树-splay】

时间:2022-12-13 04:30:35

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 

Input

第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数
接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n 

Output

输出一行n个数字,表示原始序列经过m次变换后的结果 

Sample Input

5 3

1 3

1 3

1 4

Sample Output

4 3 2 1 5

HINT

N,M<=100000

 

板子啊,常规操作

 

#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN (100000+10)
using namespace std;
int Father[MAXN];
int Son[MAXN][2];
int Size[MAXN];
int Smark[MAXN];
int a[MAXN];
int Key[MAXN];
int Root;
int n,m,l,r;
int Get(int x)
{
	return Son[Father[x]][1]==x;
}

void Update(int x)
{
	Size[x]=Size[Son[x][1]]+Size[Son[x][0]]+1;
}

void Pushdown(int x)
{
	if (x && Smark[x])
	{
		Smark[Son[x][0]]^=1;
		Smark[Son[x][1]]^=1;
		swap(Son[x][0],Son[x][1]);
		Smark[x]=0;
	}
}

void Rotate(int x)
{
	Pushdown(Father[x]);
	Pushdown(x);
	int fa=Father[x];
	int fafa=Father[fa];
	int wh=Get(x);
	
	Son[fa][wh]=Son[x][wh^1];
	Father[fa]=x;
	if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
	
	Father[x]=fafa;
	Son[x][wh^1]=fa;
	if (fafa) Son[fafa][Son[fafa][1]==fa]=x;
	
	Update(fa);
	Update(x);
}

void Splay(int x,int tar)
{
	for (int fa;(fa=Father[x])!=tar;Rotate(x))
		if (Father[fa]!=tar)
			Rotate(Get(fa)==Get(x)?fa:x);
	if (!tar) Root=x;
}

void Build (int l,int r,int fa)
{
	if (l>r) return;
	int mid=(l+r)/2;
	if (mid<fa) Son[fa][0]=mid;
	if (mid>fa) Son[fa][1]=mid;
	Father[mid]=fa;
	Size[mid]=1;
	Key[mid]=a[mid];
	if (l==r) return;
	Build(l,mid-1,mid);
	Build(mid+1,r,mid);
	Update(mid);
}

int Findx(int x)
{
	int now=Root;
	while (1)
	{
		Pushdown(now);
		if (x<=Size[Son[now][0]])
			now=Son[now][0];
		else
		{
			x-=Size[Son[now][0]];
			if (x==1) return now;
			x-=1;
			now=Son[now][1];
		}
	}
}

void Rever(int l,int r)
{
	int f1=Findx(l);
	int f2=Findx(r+2);
	Splay(f1,0);
	Splay(f2,f1);
	Smark[Son[Son[Root][1]][0]]^=1;
}

void Write(int x)
{
	Pushdown(x);
	if (Son[x][0]) Write(Son[x][0]);
	if (x>=2 && x<=n+1) printf("%d ",Key[x]);
	if (Son[x][1]) Write(Son[x][1]);
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=2;i<=n+1;++i)
		a[i]=i-1;
	Build(1,n+2,0);Root=(n+3)/2;
	for (int i=1;i<=m;++i)
	{
		scanf("%d%d",&l,&r);
		if (l>=r) continue;
		Rever(l,r);
	}
	Write(Root);
}