BZOJ2631 tree(伍一鸣) LCT 秘制标记

Posted TS_Hugh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2631 tree(伍一鸣) LCT 秘制标记相关的知识,希望对你有一定的参考价值。

这个题一看就是裸地LCT嘛,但是我wa了好几遍,这秘制标记......

注意事项:I.*对+有贡献 II.先下传*再下传+(因为我们已经维护了+,不能再让*对+产生贡献)III.维护+用到size

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 100005
#define P 51061
using namespace std;
inline unsigned int read()
{
    unsigned int sum=0;
    char ch=getchar();
    while(ch<0||ch>9)ch=getchar();
    while(ch>=0&&ch<=9)
    {
       sum=(sum<<1)+(sum<<3)+ch-0;
       ch=getchar();
    }
    return sum;
}
struct LCT
{
    struct Node
    {
        Node *ch[2],*f;
        unsigned int key,multi,pluss,sum,size;
        bool rev;
        void pushup()
        {
            sum=(key+ch[0]->sum+ch[1]->sum)%P;
            size=ch[0]->size+1+ch[1]->size;
        }
    }null[MAXN];
    void swap(Node *&x,Node *&y)
    {
        Node *temp=x;
        x=y;
        y=temp;
    }
    void pushdown(Node *p)
    {
        if(p->rev)
        {
            p->ch[0]->rev^=1;
            p->ch[1]->rev^=1;
            swap(p->ch[0],p->ch[1]);
            p->rev=0;
        }
        if(p->multi!=1)
        {
            p->ch[0]->sum=(p->ch[0]->sum*p->multi)%P;
            p->ch[0]->key=(p->ch[0]->key*p->multi)%P;
            p->ch[0]->pluss=(p->ch[0]->pluss*p->multi)%P;
            p->ch[0]->multi=(p->ch[0]->multi*p->multi)%P;
            p->ch[1]->sum=(p->ch[1]->sum*p->multi)%P;
            p->ch[1]->key=(p->ch[1]->key*p->multi)%P;
            p->ch[1]->pluss=(p->ch[1]->pluss*p->multi)%P;
            p->ch[1]->multi=(p->ch[1]->multi*p->multi)%P;
            p->multi=1;
        }
        if(p->pluss)
        {
            if(p->ch[1]!=null)
            {
               p->ch[1]->sum=(p->ch[1]->sum+p->pluss*p->ch[1]->size)%P;
               p->ch[1]->key=(p->ch[1]->key+p->pluss)%P;
               p->ch[1]->pluss=(p->ch[1]->pluss+p->pluss)%P;
            }
            if(p->ch[0]!=null)
            {
               p->ch[0]->sum=(p->ch[0]->sum+p->pluss*p->ch[0]->size)%P;
               p->ch[0]->key=(p->ch[0]->key+p->pluss)%P;
               p->ch[0]->pluss=(p->ch[0]->pluss+p->pluss)%P;
            }
            p->pluss=0;
        }
    }
    void Init()
    {
       null->ch[1]=null->ch[0]=null->f=null;
       for(unsigned int i=1;i<MAXN;i++)
        null[i].ch[0]=null[i].ch[1]=null[i].f=null,null[i].sum=null[i].key=null[i].multi=1,null[i].pluss=0;
    }
    bool isroot(Node *p)
    {
       return p->f->ch[0]!=p&&p->f->ch[1]!=p;
    }
    unsigned int get(Node *p)
    {
       return p->f->ch[1]==p;
    }
    void rotate(Node *p)
    {
       Node *fa=p->f,*pa=fa->f;
       unsigned int j=get(p);
       if(!isroot(fa))pa->ch[get(fa)]=p;
       if((fa->ch[j]=p->ch[j^1])!=null)fa->ch[j]->f=fa;
       fa->f=p;
       p->f=pa;
       p->ch[j^1]=fa;
       fa->pushup();
       p->pushup();
    }
    void spaly(Node *p)
    {
        pushdown(p);
        for(Node *fa=p->f;!isroot(p);rotate(p),fa=p->f)
        if(!isroot(fa))
        {
            pushdown(fa->f),pushdown(fa),pushdown(p);
            rotate(get(fa)==get(p)?fa:p);
        }
        else 
            pushdown(fa),pushdown(p);
    }
    void expose(Node *x)
    {
        Node *y=null;
        while(x!=null)
        {
           spaly(x);
           x->ch[1]=y;
           x->pushup();
           y=x;
           x=x->f;
        }
    }
    void make_root(Node *p)
    {
        expose(p);
        spaly(p);
        p->rev^=1;
    }
    void cut(unsigned int a,unsigned int b)
    {
        Node *x=null+a,*y=null+b;
        make_root(x);
        expose(y);
        spaly(y);
        y->ch[0]->f=null;
        y->ch[0]=null;
        y->pushup();
    }
    void link(unsigned int a,unsigned int b)
    {
        Node *x=null+a,*y=null+b;
        make_root(x);
        x->f=y;
    }
    void up(unsigned int a,unsigned int b,unsigned int c)
    {
        Node *x=null+a,*y=null+b;
        make_root(x);
        expose(y);
        spaly(y);
        y->pluss=(y->pluss+c)%P;
        y->key=(y->key+c)%P;
        y->sum=(y->sum+y->size*c)%P;
    }
    void UUP(unsigned int a,unsigned int b,unsigned int c)
    {
        Node *x=null+a,*y=null+b;
        make_root(x);
        expose(y);
        spaly(y);
        y->multi=(y->multi*c)%P;
        y->key=(y->key*c)%P;
        y->sum=(y->sum*c)%P;
        y->pluss=(y->pluss*c)%P;
    }
    unsigned int query(unsigned int a,unsigned int b)
    {
        Node *x=null+a,*y=null+b;
        make_root(x);
        expose(y);
        spaly(y);
        return y->sum;
    }
}YY;
int main()
{
    YY.Init();
    unsigned int n=read(),m=read();
    for(unsigned int i=1;i<n;i++)
    {
       unsigned int x=read(),y=read();
       YY.link(x,y);
    }
    for(unsigned int i=1,x,y,z,a,b;i<=m;i++)
    {
       char ch;
       cin>>ch;
       x=read(),y=read();
       switch(ch)
       {
           case *:z=read();
                    YY.UUP(x,y,z);
                    break;
           case +:z=read();
                    YY.up(x,y,z);
                    break;
           case -:a=read(),b=read();
                    YY.cut(x,y);
                    YY.link(a,b);
                    break;
           case /:printf("%d\n",YY.query(x,y));
                    break;
       }
    }
    return 0;
}

 

以上是关于BZOJ2631 tree(伍一鸣) LCT 秘制标记的主要内容,如果未能解决你的问题,请参考以下文章

国家集训队2012tree(伍一鸣)

BZOJ2631: tree

BZOJ 2631 tree 动态树(Link-Cut-Tree)

[国家集训队2012]tree(伍一鸣)

BZOJ2049,2631,3282,1180LCT模板四连A

bzoj2631