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;
}
posted @ 2020-08-11 09:11  GK0328  阅读(88)  评论(0编辑  收藏  举报