文艺平衡树

思路

splay确实有点绕
还是fhq-treap牛逼啊,构造完美二叉树(他们说笛卡尔树),就不用rand的,直接计算就好
时间也不慢

代码

#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn=1e5+7;
const int inf=0x3f3f3f3f;
typedef long long ll;
int read() {
	int x=0,f=1;
	char s=getchar();
	for(; s>'9'||s<'0'; s=getchar()) if(s=='-') f=-1;
	for(; s>='0'&&s<='9'; s=getchar()) x=x*10+s-'0';
	return x*f;
}
int n,m,rt;
int ch[maxn][2],tag[maxn],val[maxn],size[maxn],pri[maxn],cnt;
void pushup(int a) {
	size[a]=size[ch[a][0]]+size[ch[a][1]]+1;
}
void pushdown(int a) {
	if(!tag[a]) return;
	tag[ch[a][0]]^=1;
	tag[ch[a][1]]^=1;
	swap(ch[a][0],ch[a][1]);
	tag[a]=0;
}
int merge(int x,int y) {
	if(!x||!y) return x+y;
	pushdown(x);
	pushdown(y);
	if(pri[x]<pri[y]) {
		ch[x][1]=merge(ch[x][1],y);
		pushup(x);
		return x;
	} else {
		ch[y][0]=merge(x,ch[y][0]);
		pushup(y);
		return y;
	}
}
void split(int now,int k,int &x,int &y) {
	if(!now) x=y=0;
	else {
		pushdown(now);
		if(size[ch[now][0]]+1<=k) x=now,split(ch[now][1],k-size[ch[now][0]]-1,ch[x][1],y);
		else y=now,split(ch[now][0],k,x,ch[y][0]);
		pushup(now);
	}
}
int build(int l,int r) {
	if(l>r) return 0;
	int mid=(l+r)>>1,p=++cnt;
	val[p]=mid;
	size[p]=1;
	pri[p]=cnt;
	ch[p][0]=build(l,mid-1);
	ch[p][1]=build(mid+1,r);
	pushup(p);
	return p;
}
void dfs(int now) {
	pushdown(now);
	if(!now) return;
	dfs(ch[now][0]);
	cout<<val[now]<<" ";
	dfs(ch[now][1]);
} 
int main() {
	n=read(),m=read();
	rt=build(1,n);
	int x,y,z;
	FOR(i,1,m) {
		int a=read(),b=read();
		split(rt,a-1,x,y);
		split(y,b-a+1,y,z);
		tag[y]^=1;
		rt=merge(merge(x,y),z);
	}
	dfs(rt);
	return 0;
}
原文地址:https://www.cnblogs.com/dsrdsr/p/10050878.html