[SHOI2014]三叉神经树,洛谷P4332,LCT

正题

      难度虚高

      想一想就会做了,直接用ans[0/1]来维护将0/1放进当前点的splay的末端得出来的信息,那些非节点的权值和轻儿子的权值用一个tot来维护,acs的时候直接更改,upd就看看将0/1放进右儿子会有什么答案,然后再算自己,在丢到左儿子.代码比其他LCT的都短,因为不用换根,就少了dfs下放标记和psd.

#include<bits/stdc++.h>
using namespace std;

const int N=1500010;
struct node{
	int son[2],fa,tot;
	bool ans[2];
}s[N];
int a[N],n,q;
#define ls s[x].son[0]
#define rs s[x].son[1]
void upd(int x){
	s[x].ans[0]=s[ls].ans[(s[rs].ans[0]+s[x].tot)/2];
	s[x].ans[1]=s[ls].ans[(s[rs].ans[1]+s[x].tot)/2];
}
bool isrt(int x){return s[s[x].fa].son[0]!=x && s[s[x].fa].son[1]!=x;};
void rotate(int x){
	int f=s[x].fa,ff=s[f].fa;
	bool w=s[f].son[1]==x;
	if(!isrt(f)) s[ff].son[s[ff].son[1]==f]=x;s[x].fa=ff;
	s[f].son[w]=s[x].son[w^1];s[s[x].son[w^1]].fa=f;
	s[f].fa=x;s[x].son[w^1]=f;
	upd(f);upd(x);
}
void splay(int x){
	while(!isrt(x)){
		int f=s[x].fa,ff=s[f].fa;
		if(!isrt(f)) s[ff].son[1]==f^s[f].son[1]==x?rotate(x):rotate(f);
		rotate(x);
	}
}
void acs(int x){
	for(int las=0;x;las=x,x=s[x].fa)
		splay(x),s[x].tot+=s[rs].ans[0]-s[las].ans[0],rs=las,upd(x);
}
void chg(int x,int t){acs(x);splay(x);s[x].tot+=t;upd(x);}

int main(){
	scanf("%d",&n);
	int x;s[0].ans[1]=1;
	for(int i=1;i<=n;i++) for(int j=0;j<3;j++){scanf("%d",&x),s[x].fa=i;}
	for(int i=n+1;i<=3*n+1;i++){
		scanf("%d",&a[i]);
		if(a[i]) chg(s[i].fa,1);
	}
	scanf("%d",&q);
	while(q--){
		scanf("%d",&x);a[x]^=1;
		chg(s[x].fa,a[x]==1?1:-1);
		printf("%d\n",s[s[x].fa].ans[0]);
	}
}

猜你喜欢

转载自blog.csdn.net/Deep_Kevin/article/details/108351695