「SHOI2014」三叉神经树 解题报告

「SHOI2014」三叉神经树

膜拜神仙思路

我们想做一个类似于动态dp的东西,首先得确保我们的运算有一个交换律,这样我们可以把一长串的运算转换成一块一块的放到矩阵上之类的东西,然后拿数据结构维护。

但是考虑这个题,它最下面的那个运算的输入端只有两种可能,于是我们只需要讨论一下初始输入就完事了。

具体的,\(LCT\)每条实链维护一个\(yuu[i][0/1]\)表示实链底端的点输入为\(0/1\)后链头输出什么。

注意,这个链头指的是\(splay\)中那个点\(i\)的子树代表的那条链,也就是说链头是点\(i\)子树最左边的点。

那么单独的一个点没有实儿子一定输入\(0\),因为最深的儿子没有实儿子,于是整个链的输入也是\(0\)

当然我们肯定需要维护一个虚儿子的信息,它可以使某一条链(splay中的某子树)的输出为\(1\)然后再传给它的父亲之类的

另外,\(yuu\)的全称是小糸侑(\(Koito \ Yuu\))


Code:

#include <cstdio>
#include <cctype>
#define ls ch[now][0]
#define rs ch[now][1]
#define fa par[now]
const int N=2e6+10;
template <class T>
void read(T &x)
{
	x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
int yuu[N][2],ch[N][2],par[N],bee[N],si[N],n,q;
void updata(int now)
{
	yuu[now][0]=si[now]>1;
	yuu[now][1]=si[now]>0;
	if(rs)
	{
		if(yuu[rs][0]) yuu[now][0]=yuu[now][1];
		else if(!yuu[rs][1]) yuu[now][1]=yuu[now][0];
	}
	if(ls)
	{
		if(yuu[now][0]) yuu[now][0]=yuu[now][1]=yuu[ls][1];
		else if(!yuu[now][1]) yuu[now][0]=yuu[now][1]=yuu[ls][0];
		else yuu[now][0]=yuu[ls][0],yuu[now][1]=yuu[ls][1];
	}
}
int identity(int now){return ch[fa][1]==now;}
int isroot(int now){return ch[fa][0]==now||ch[fa][1]==now;}
void connect(int f,int now,int typ){ch[fa=f][typ]=now;}
void Rotate(int now)
{
	int p=fa,typ=identity(now);
	connect(p,ch[now][typ^1],typ);
	if(isroot(p)) connect(par[p],now,identity(p));
	else fa=par[p];
	connect(now,p,typ^1);
	updata(p),updata(now);
}
void splay(int now)
{
	for(;isroot(now);Rotate(now))
		if(isroot(fa))
			Rotate(identity(now)^identity(fa)?now:fa);
}
void access(int now)
{
	for(int las=0;now;las=now,now=fa)
	{
		splay(now),si[now]-=yuu[las][0],si[now]+=yuu[rs][0];
		rs=las,updata(now);
	}
}
int head[N],to[N],Next[N],cnt;
void add(int u,int v)
{
	to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
void dfs(int now)
{
	if(now>n) return;
	for(int i=head[now];i;i=Next[i])
		dfs(to[i]),si[now]+=bee[to[i]];
	bee[now]=yuu[now][0]=si[now]>1;
	yuu[now][1]=si[now]>0;
}
int main()
{
	read(n);
	for(int x,i=1;i<=n;i++)
	{
		read(x),par[x]=i,add(i,x);
		read(x),par[x]=i,add(i,x);
		read(x),par[x]=i,add(i,x);
	}
	for(int i=n+1;i<=3*n+1;i++) read(bee[i]);
	dfs(1);
	read(q);
	for(int x,now,i=1;i<=q;i++)
	{
		read(x),now=par[x];
		access(now),splay(now);
		bee[x]^=1;
		si[now]+=bee[x]?1:-1;
		updata(now);
		putchar(yuu[now][0]?'1':'0'),putchar('\n');
	}
	return 0;
}

2019.2.24

posted @ 2019-02-24 14:35  露迭月  阅读(225)  评论(0编辑  收藏  举报