文艺平衡树

link

平衡树(特别是Splay)维护序列的模板题。之前实在是我傻了调了那么久……

首先明确几个概念,正是这几个概念的模糊导致了我对算法理解的不清晰和极其蹩脚的调试过程。

会考虑维护一棵平衡树,它的中序遍历就是原序列。区间操作是基于对子树的整体操作的,假如有一个针对\([l,r]\)的修改或查询,考虑把\(l-1\)节点旋转到树根,把\(r+1\)节点旋转到树根的右儿子处(会发现为了防止访问到奇怪东西,可以先在子Splay里插入0号点和m+1号点),这样树根右儿子的左儿子对应的就是修改区间。找寻序列中某个位置对应的节点考虑使用奇怪方法,边向下走边更新查找值即可。其它都还好,调了这么久完全因为我是傻逼。

#include<cstdio>
#define zczc
const int N=100010;
const int maxn=1e9;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
inline void swap(int &s1,int &s2){int s3=s1;s1=s2;s2=s3;return;}

#define lc t[x].ch[0]
#define rc t[x].ch[1]
int m,n,root,cnt,a[N];
struct node{int ch[2],f,size,nb;bool lazy;}t[N];
inline void pushup(int x){t[x].size=t[lc].size+t[rc].size+1;}
inline void link(int x,int kk,int y){t[x].ch[kk]=y;t[y].f=x;}
inline void pushdown(int x){
	if(!x||t[x].lazy==false)return;t[x].lazy=false;
	t[lc].lazy^=1,t[rc].lazy^=1,swap(lc,rc);
}
inline void rotate(int x){
	int y=t[x].f;int z=t[y].f,kk=t[y].ch[1]==x;
	pushdown(y);pushdown(x);
	link(z,t[z].ch[1]==y,x);
	link(y,kk,t[x].ch[kk^1]);
	link(x,kk^1,y);pushup(y);pushup(x);
}
inline void splay(int x,int rt){
	while(t[x].f^rt){
		int y=t[x].f;int z=t[y].f;
		if(z^rt)(t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);rotate(x);
	}if(rt==0)root=x;
}
int build(int l,int r,int ff){
	if(l>r)return 0;int x=++cnt,mid=l+r>>1;
	t[x].size=1,t[x].nb=a[mid],t[x].f=ff;
	return lc=build(l,mid-1,x),rc=build(mid+1,r,x),pushup(x),x;
}
int find(int val){
	int x=root;
	while(x){
		pushdown(x);if(val<=t[lc].size)x=lc;
		else{val-=t[lc].size+1;if(!val)return x;x=rc;}
	}
}
void dfs(int x){
	if(!x)return;pushdown(x);dfs(lc);if(t[x].nb!=maxn)printf("%d ",t[x].nb);dfs(rc);
}

#undef lc
#undef rc

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	read(m);read(n);for(int i=1;i<=m;i++)a[i+1]=i;a[1]=a[m+2]=maxn;
	root=build(1,m+2,root);
	while(n--){
		int l,r;read(l);read(r);int sl=find(l),sr=find(r+2);
		splay(sl,0);splay(sr,sl);t[t[sr].ch[0]].lazy^=1;
	}
	dfs(root);
	
	return 0;
}
posted @ 2022-02-12 13:57  Feyn618  阅读(70)  评论(0编辑  收藏  举报