BZOJ 2243 染色(动态树)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2243

题意:一棵树,初始时每个节点有一个颜色。两种操作:(1)将某条路经上的点的颜色统一修改为某个值;(2)统计某条路径上颜色有多少段?比如11221算3段。

思路:splay节点记录区间的左右两侧的颜色LR,该节点的颜色val以及总的段数以及标记。向上合并时根据左孩子右孩子的LR以及当前节点的val计算当前子树的段数。修改时,[x,y],先access(x)使得x与lca在一起。然后从y向上,直到找到lca,y和lca的右子树标记修改,lca直接修改。这里要注意,lca的右子树和y要判断是不是为nullNode,在这里wa两个小时。。。统计答案时与修改类似。

 

struct node

{

    int L,R,val,sum,flag;

    node *c[2],*p;



    void set(int color)

    {

        L=R=val=flag=color;

        sum=1;

    }

};



node a[N],*nullNode;





void pushUp(node *p)

{

    if(p==nullNode) return;

    p->sum=1;

    p->L=p->R=p->val;

    if(p->c[0]!=nullNode)

    {

        if(p->c[0]->R==p->L) p->sum+=p->c[0]->sum-1;

        else p->sum+=p->c[0]->sum;

        p->L=p->c[0]->L;

    }

    if(p->c[1]!=nullNode)

    {

        if(p->c[1]->L==p->R) p->sum+=p->c[1]->sum-1;

        else p->sum+=p->c[1]->sum;

        p->R=p->c[1]->R;

    }

}



void pushDown(node *p)

{

    if(p==nullNode) return;

    if(p->flag!=-1)

    {

        if(p->c[0]!=nullNode) p->c[0]->set(p->flag);

        if(p->c[1]!=nullNode) p->c[1]->set(p->flag);

        p->flag=-1;

    }

}



int isRoot(node *p)

{

    return p->p==nullNode||p->p->c[0]!=p&&p->p->c[1]!=p;

}





node *zig(node *x)

{

    node *p=x->p,*q=p->p;

    p->c[0]=x->c[1];

    if(x->c[1]!=nullNode) x->c[1]->p=p;

    x->c[1]=p;

    p->p=x;

    x->p=q;

    if(q!=nullNode)

    {

        if(q->c[0]==p) q->c[0]=x;

        if(q->c[1]==p) q->c[1]=x;

    }

    pushUp(p);

    pushUp(x);

}



node *zag(node *x)

{

    node *p=x->p,*q=p->p;

    p->c[1]=x->c[0];

    if(x->c[0]!=nullNode) x->c[0]->p=p;

    x->c[0]=p;

    p->p=x;

    x->p=q;

    if(q!=nullNode)

    {

        if(q->c[0]==p) q->c[0]=x;

        if(q->c[1]==p) q->c[1]=x;

    }

    pushUp(p);

    pushUp(x);

}







void splay(node *x)

{

    pushDown(x);

    while(!isRoot(x))

    {

        if(!isRoot(x->p))

        {

            pushDown(x->p->p);

            pushDown(x->p);

            pushDown(x);

            if(x->p->p->c[0]==x->p)

            {

                if(x->p->c[0]==x) zig(x->p),zig(x);

                else zag(x),zig(x);

            }

            else

            {

                if(x->p->c[1]==x) zag(x->p),zag(x);

                else zig(x),zag(x);

            }

        }

        else

        {

            pushDown(x->p);

            pushDown(x);

            if(x->p->c[0]==x) zig(x);

            else zag(x);

        }

    }

}





node *access(node *x)

{

    node *p=nullNode;

    while(x!=nullNode)

    {

        splay(x);

        x->c[1]=p;

        pushUp(x);

        p=x;

        x=x->p;

    }

    return p;

}



int cal(int x,int y)

{

    access(a+x);

    node *lca=access(a+y);

    splay(a+x);



    int ans;



    if(lca!=a+x)

    {

        ans=lca->c[1]->sum+a[x].sum+1;

        if(lca->c[1]->L==lca->val) ans--;

        if(a[x].L==lca->val) ans--;

    }

    else

    {

        ans=lca->c[1]->sum+1;

        if(lca->c[1]->L==lca->val) ans--;

    }

    return ans;

}





void color(int x,int y,int val)

{

    access(a+x);

    node *lca=access(a+y);



    splay(a+x);



    if(a+x!=lca)

    {

        if(a+x!=nullNode) a[x].set(val);

        if(lca->c[1]!=nullNode) lca->c[1]->set(val);

        lca->val=val;

    }

    else

    {

        if(lca->c[1]!=nullNode) lca->c[1]->set(val);

        lca->val=val;

    }



    pushUp(lca);



}





vector<int> g[N];

int n,m,C[N];





void build()

{

    queue<int> Q;

    Q.push(1);

    a[1].c[0]=a[1].c[1]=a[1].p=nullNode;

    a[1].L=a[1].R=a[1].val=C[1];

    a[1].sum=1;

    a[1].flag=-1;

    int i,u,v;

    while(!Q.empty())

    {

        u=Q.front();

        Q.pop();

        FOR0(i,SZ(g[u]))

        {

            v=g[u][i];

            if(a+v==a[u].p) continue;

            a[v].p=a+u;

            a[v].c[0]=a[v].c[1]=nullNode;

            a[v].L=a[v].R=a[v].val=C[v];

            a[v].sum=1;

            a[v].flag=-1;

            Q.push(v);

        }

    }

}



void init()

{

    nullNode=new node();

    nullNode->L=nullNode->R=nullNode->val=-2;

    nullNode->sum=0;

    nullNode->c[0]=nullNode->c[1]=nullNode->p=nullNode;



    RD(n,m);

    int i,x,y;

    FOR1(i,n) RD(C[i]);

    FOR1(i,n-1)

    {

        RD(x,y);

        g[x].pb(y);

        g[y].pb(x);

    }

    build();

}



int main()

{

    init();

    char op[5];

    int x,y,z;

    while(m--)

    {

        RD(op);

        if(op[0]=='Q')

        {

            RD(x,y);

            PR(cal(x,y));

        }

        else

        {

            RD(x,y,z);

            color(x,y,z);

        }

    }

}

 

 

 

你可能感兴趣的:(ZOJ)