• bzoj 2631: tree -- LCT


    2631: tree

    Time Limit: 30 Sec  Memory Limit: 128 MB

    Description

     一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
    + u v c:将u到v的路径上的点的权值都加上自然数c;
    - u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
    * u v c:将u到v的路径上的点的权值都乘上自然数c;
    / u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。

     

    Input

      第一行两个整数n,q
    接下来n-1行每行两个正整数u,v,描述这棵树
    接下来q行,每行描述一个操作
     

    Output

      对于每个/对应的答案输出一行
     

    Sample Input

    3 2
    1 2
    2 3
    * 1 3 4
    / 1 1

    Sample Output

    4


    HINT

    数据规模和约定

    10%的数据保证,1<=n,q<=2000

    另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链

    另外35%的数据保证,1<=n,q<=5*10^4,没有-操作

    100%的数据保证,1<=n,q<=10^5,0<=c<=10^4


    Source

    LCT入门题,,

    md一个%=写成了%改了我一天。。。

    #include<map>
    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define inf 1000000007
    #define ll long long
    #define uint unsigned int
    #define mod 51061
    #define N 100010
    inline int rd()
    {
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    int c[N][2],fa[N],sz[N];
    uint lz1[N],lz2[N],v[N],sum[N];
    bool rev[N];
    int n,q;
    #define ls c[x][0]
    #define rs c[x][1]
    bool isrt(int x){return x!=c[fa[x]][0]&&x!=c[fa[x]][1];}
    inline void pd(int x)
    {
        uint mz;
        if(rev[x])
        {
            rev[ls]^=1;rev[rs]^=1;
            swap(ls,rs);rev[x]=0;
        }
        mz=lz2[x];lz2[x]=1;
        if(mz!=1)
        {
            lz2[ls]=lz2[ls]*mz%mod;
            lz2[rs]=lz2[rs]*mz%mod;
            lz1[ls]=lz1[ls]*mz%mod;
            lz1[rs]=lz1[rs]*mz%mod;
            sum[ls]=sum[ls]*mz%mod;
            sum[rs]=sum[rs]*mz%mod;
            v[ls]=v[ls]*mz%mod;v[rs]=v[rs]*mz%mod;
        }
        mz=lz1[x];lz1[x]=0;
        if(mz)
        {
            (lz1[ls]+=mz)%=mod;
            (lz1[rs]+=mz)%=mod;
            (sum[ls]+=sz[ls]*mz)%=mod;
            (sum[rs]+=sz[rs]*mz)%=mod;
            (v[ls]+=mz)%=mod;(v[rs]+=mz)%=mod;
        }
    }
    inline void upd(int x)
    {
        sz[x]=sz[ls]+sz[rs]+1;
        sum[x]=(v[x]+sum[ls]+sum[rs])%mod;
    }
    void rot(int x)
    {
        int y=fa[x],z=fa[y],l,r;
        l=c[y][1]==x;r=l^1;
        if(!isrt(y)) c[z][c[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        upd(y);upd(x);
    }
    
    int st[N],tot;
    void splay(int x)
    {
        tot=1;st[1]=x;
        for(int i=x;!isrt(i);i=fa[i]) st[++tot]=fa[i];
        for(int i=tot;i;i--) pd(st[i]);
        int y,z;
        while(!isrt(x))
        {
            y=fa[x];z=fa[y];
            if(!isrt(y))
            {
                if((c[y][0]==x)^(c[z][0]==y)) rot(x);
                else rot(y);
            }
            rot(x);
        }
    }
    void acc(int x)
    {
        int t=0;
        while(x)
        {
            splay(x);
            rs=t;upd(x);
            t=x;x=fa[x];
        }
    }
    void rever(int x)
    {
        acc(x);
        splay(x);
        rev[x]^=1;
    }
    void mk(int x,int y)
    {
        rever(x);
        acc(y);splay(y);
    }
    void link(int x,int y)
    {
        rever(x);
        fa[x]=y;
    }
    void cut(int x,int y)
    {
        mk(x,y);
        c[y][0]=fa[x]=0;
    }
    inline void mul(int x,int V)
    {
        (v[x]*=V)%=mod;
        (sum[x]*=V)%=mod;
        (lz2[x]*=V)%=mod;
        (lz1[x]*=V)%=mod;
    }
    inline void add(int x,int V)
    {
        (v[x]+=V)%=mod;
        (sum[x]+=V*sz[x])%=mod;
        (lz1[x]+=V)%=mod;
    }
    int main()
    {
        n=rd();q=rd();
        for(int i=1;i<=n;i++) lz2[i]=sz[i]=sum[i]=v[i]=1;
        for(int i=1,x,y;i<n;i++)
        {
            x=rd();y=rd();
            link(x,y);
        }
        char op[2];
        int x,y,xx,yy,V;
        while(q--)
        {
            scanf("%s",op);
            if(op[0]=='*')
            {
                x=rd();y=rd();V=rd();
                mk(x,y);mul(y,V);
            }
            else if(op[0]=='+')
            {
                x=rd();y=rd();V=rd();
                mk(x,y);add(y,V);
            }
            else if(op[0]=='-')
            {
                x=rd();y=rd();xx=rd();yy=rd();
                cut(x,y);link(xx,yy);
            }
            else 
            {
                x=rd();y=rd();
                mk(x,y);printf("%d
    ",sum[y]);
            }
        }
        return 0;
    }
  • 相关阅读:
    Oracle日期函数大全
    Android Permission(授权)大全
    澳大利亚项目VBA部分简略代码
    Android模拟器安装程序及上传音乐并播放
    更改电脑背景颜色,保护您的眼睛
    编写高效Excel VBA代码的最佳实践(一)
    VBA复制粘贴效率问题
    编写高效Excel VBA代码的最佳实践(二)
    编写高效Excel VBA代码的最佳实践(二)
    Android新浪星座运势程序开发
  • 原文地址:https://www.cnblogs.com/lkhll/p/8075415.html
Copyright © 2020-2023  润新知