Luogu4332 [SHOI2014]三叉神经树
https://www.luogu.com.cn/problem/P4332
\(LCT\)
可以发现,将叶子节点的\(0\)变为\(1\),只会影响它上面输入值为\(1\)的一串祖先及第一个值不为\(1\)的节点\(n1\);将叶子节点的\(1\)变为\(0\),只会影响它上面输入值为\(2\)的一串祖先及第一个值不为\(2\)的节点\(n2\)
我们维护以一个节点为根最深的值不为\(1\)的节点和值不为\(2\)的节点
然后我们区间修改一条链(该节点的子孙,都是值均为\(1\)或\(2\)的节点),再单点修改该节点即可,如果找不到最深的值不为\(1\)的节点或值不为\(2\)的节点,直接整棵树修改(它们的值必定均为\(1\)或\(2\))
注意,打上加法标记时,要顺手修改\(n1,n2\),由于做加法标记的都是值均为\(1\)或\(2\)的节点,对于值均为\(1\)的节点,\(n2=n1,n1=0\)(显然,操作后,所有节点值都为\(2\)),另一类节点同理,\(n1=n2,n2=0\)
之所以要这么做,我们已经钦定了,当我们修改一个节点所代表的区间时,它的本身值应当被更新为正确的值
\(C++ Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define fa(x) a[x].f
#define ls(x) a[x].ch[0]
#define rs(x) a[x].ch[1]
#define v(x) val[x]
#define c(x) a[x].cnt
#define n1(x) a[x].not_equal_to_1
#define n2(x) a[x].not_equal_to_2
#define tag1(x) a[x].tag_add
#define id(x) ((ls(fa(x))==x)?0:1)
#define N 1500005
using namespace std;
queue<int>que;
int n,Q,x,y,z,g,d[N],q[N],val[N];
bool need;
struct node
{
int ch[2],f,cnt,not_equal_to_1,not_equal_to_2,tag_add;
}a[N];
void update(int x)
{
n1(x)=n1(rs(x));
if (!n1(x))
n1(x)=(x>n || c(x)==1)?n1(ls(x)):x;
n2(x)=n2(rs(x));
if (!n2(x))
n2(x)=(x>n || c(x)==2)?n2(ls(x)):x;
}
void push_add(int x,int z)
{
c(x)+=z;
tag1(x)+=z;
if (z>0)
n2(x)=n1(x),n1(x)=0; else
n1(x)=n2(x),n2(x)=0;
}
void pushdown(int x)
{
if (tag1(x))
{
if (ls(x))
push_add(ls(x),tag1(x));
if (rs(x))
push_add(rs(x),tag1(x));
tag1(x)=0;
}
}
void connect(int x,int F,int son)
{
fa(x)=F;
a[F].ch[son]=x;
}
bool isrt(int x)
{
return ls(fa(x))!=x && rs(fa(x))!=x;
}
void rot(int x)
{
int y=fa(x),r=fa(y);
int yson=id(x),rson=id(y);
if (isrt(y))
fa(x)=r; else
connect(x,r,rson);
connect(a[x].ch[yson^1],y,yson);
connect(y,x,yson^1);
update(y),update(x);
}
void splay(int x)
{
int g=x,k=0;
q[++k]=g;
while (!isrt(g))
{
g=fa(g);
q[++k]=g;
}
while (k)
pushdown(q[k--]);
while (!isrt(x))
{
int y=fa(x);
if (isrt(y))
rot(x); else
if (id(x)==id(y))
rot(y),rot(x); else
rot(x),rot(x);
}
}
void access(int x)
{
for (int y=0;x;y=x,x=fa(x))
splay(x),rs(x)=y,update(x);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&z);
d[fa(x)=fa(y)=fa(z)=i]=3;
}
for (int i=n+1;i<=n+n+n+1;i++)
scanf("%d",&v(i)),c(i)=v(i);
for (int i=1;i<=n+n+n+1;i++)
if (!d[i])
que.push(i);
while (!que.empty())
{
int u=que.front();
que.pop();
if (u<=n)
v(u)=c(u)>1;
c(fa(u))+=v(u);
d[fa(u)]--;
if (!d[fa(u)])
que.push(fa(u));
}
scanf("%d",&Q);
while (Q --> 0)
{
scanf("%d",&x);
access(x);
splay(x);
if (c(x)==0)
{
g=n1(x);
if (!g)
push_add(x,1); else
{
splay(g);
if (rs(g))
push_add(rs(g),1);
c(g)++;
update(g);
}
} else
{
g=n2(x);
if (!g)
push_add(x,-1); else
{
splay(g);
if (rs(g))
push_add(rs(g),-1);
c(g)--;
update(g);
}
}
v(x)^=1;
splay(1);
printf("%d\n",c(1)>1);
}
return 0;
}