为什么splay里一开始要将所有标记都下传?
查看原帖
为什么splay里一开始要将所有标记都下传?
164432
suxxsfekkksd11楼主2020/8/6 19:01

题解里的写法是在 splay的一开始把路径上的所有信息下传,用一个 pushall 函数,大概是这样:

	inline void rotate(tr *tree){
		tr *fa=tree->fa,*faa=fa->fa;
		int k=ident(tree,fa);
		connect(tree->son[k^1],fa,k);
		tree->fa=faa;
		if(notroot(fa)) faa->son[ident(fa,faa)]=tree;
		connect(fa,tree,k^1);
		pushup(fa);pushup(tree);
	}
		void pushall(tr *tree){
			if(notroot(tree)) pushall(tree->fa);
			pushdown(tree);
		}
	inline void splay(tr *tree){
		pushall(tree);
		reg tr *fa,*faa;
		while(notroot(tree)){
			fa=tree->fa;faa=fa->fa;
			if(notroot(fa)) ident(fa,faa)^ident(tree,fa)?rotate(tree):rotate(fa);
			rotate(tree);
		}
	}

然后我口胡了一种,是在 rotate 函数里下传(文艺平衡树就是这样写的,当时没问题),不 pushall。但样例二就过不了了:

	inline void pushdown(tr *tree){
		if(!tree->tag) return;
		tree->son[0]->tag^=1;tree->son[1]->tag^=1;
		std::swap(tree->son[0],tree->son[1]);
		tree->tag=0;
	}
	inline void rotate(tr *tree){
		tr *fa=tree->fa,*faa=fa->fa;
		pushdown(fa);pushdown(tree);
		int k=ident(tree,fa);
		connect(tree->son[k^1],fa,k);
		tree->fa=faa;
		if(notroot(fa)) faa->son[ident(fa,faa)]=tree;
		connect(fa,tree,k^1);
		pushup(fa);pushup(tree);
	}
	inline void splay(tr *tree){
		reg tr *fa,*faa;
		while(notroot(tree)){
			fa=tree->fa;faa=fa->fa;
			if(notroot(fa)) ident(fa,faa)^ident(tree,fa)?rotate(tree):rotate(fa);
			rotate(tree);
		}
	}

求助大佬为什么第二种不对/kel

2020/8/6 19:01
加载中...