zoukankan      html  css  js  c++  java
  • 洛谷P1501 [国家集训队]Tree II(打标记lct)

    题目描述

    一棵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的余数。

    输入输出格式

    输入格式:

     

    第一行两个整数n,q

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

    接下来q行,每行描述一个操作

     

    输出格式:

     

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

     

    输入输出样例

    输入样例#1: 复制
    3 2
    1 2
    2 3
    * 1 3 4
    / 1 1
    输出样例#1: 复制
    4
    

    说明

    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

    By (伍一鸣)

    题解:这题其实没有什么很难的地方,主要考点就是lct的打标记(还是两个orz),显然链修改跟线段树的打标记是一样的

    就是酱紫了~

    结果%=写成%调了一个晚上2333

    代码如下

    #include<map>
    #include<set>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 100010
    #define mod 51061
    #define lson ch[x][0]
    #define rson ch[x][1]
    #define int long long
    using namespace std;
    
    int tag1[N],tag2[N],tag3[N],sum[N],sz[N],f[N],ch[N][2],w[N];
    
    int not_root(int now)
    {
        int x=f[now];
        return lson==now||rson==now;
    }
    
    int push_up(int x)
    {
        sum[x]=(sum[lson]+sum[rson]+w[x])%mod;
        sz[x]=sz[lson]+sz[rson]+1;
    }
    
    int rev(int x)
    {
        swap(lson,rson);
        tag1[x]^=1;
    }
    
    int add(int x,int cost)
    {
        sum[x]+=cost*sz[x];
        sum[x]%=mod;
        w[x]+=cost;
        w[x]%=mod;
        tag2[x]+=cost;
        tag2[x]%=mod;
    }
    
    int mul(int x,int cost)
    {
        sum[x]*=cost;
        sum[x]%=mod;
        w[x]*=cost;
        w[x]%=mod;
        tag3[x]*=cost;
        tag3[x]%=mod;
        tag2[x]*=cost;
        tag2[x]%=mod;
    }
    
    int push_down(int x)
    {
        if(tag3[x]!=1)
        {
            mul(lson,tag3[x]);
            mul(rson,tag3[x]);
            tag3[x]=1;
        }
        if(tag2[x])
        {
            add(lson,tag2[x]);
            add(rson,tag2[x]);
            tag2[x]=0;
        }
        if(tag1[x])
        {
            rev(lson);
            rev(rson);
            tag1[x]=0;
        }
    }
    
    int rotate(int x)
    {
        int y=f[x],z=f[y],kd=ch[y][1]==x,xs=ch[x][!kd];
        if(not_root(y))
        {
            ch[z][ch[z][1]==y]=x;
        }
        ch[x][!kd]=y;
        ch[y][kd]=xs;
        if(xs) f[xs]=y;
        f[y]=x;
        f[x]=z;
        push_up(y);
    }
    
    int push_all(int x)
    {
        if(not_root(x))
        {
            push_all(f[x]);
        }
        push_down(x);
    }
    
    int splay(int x)
    {
        int y,z;
        push_all(x);
        while(not_root(x))
        {
            y=f[x],z=f[y];
            if(not_root(y))
            {
                (ch[y][0]==x)^(ch[z][0]==y)?rotate(x):rotate(y);
            }
            rotate(x);
        }
        push_up(x);
    }
    
    int access(int x)
    {
        for(int y=0; x; y=x,x=f[x])
        {
            splay(x);
            rson=y;
            push_up(x);
        }
    }
    
    int make_root(int x)
    {
        access(x);
        splay(x);
        rev(x);
    }
    
    int split(int x,int y)
    {
        make_root(x);
        access(y);
        splay(y);
    }
    
    int link(int x,int y)
    {
        make_root(x);
        f[x]=y;
    }
    
    int cut(int x,int y)
    {
        split(x,y);
        f[x]=ch[y][0]=0;
    }
    
    char s[3];
    int n,m;
    
    signed main()
    {
        scanf("%lld %lld",&n,&m);
        for(int i=1; i<=n; i++)
        {
            sum[i]=w[i]=tag3[i]=sz[i]=1;
        }
        for(int i=1; i<n; i++)
        {
            int from,to;
            scanf("%lld %lld",&from,&to);
            link(from,to);
        }
        for(int i=1; i<=m; i++)
        {
            scanf("%s",s);
            if(s[0]=='*')
            {
                int x,y,cost;
                scanf("%lld %lld %lld",&x,&y,&cost);
                split(y,x);
                mul(x,cost);
            }
            if(s[0]=='-')
            {
                int u1,v1,u2,v2;
                scanf("%lld %lld %lld %lld",&u1,&v1,&u2,&v2);
                cut(u1,v1);
                link(u2,v2);
            }
            if(s[0]=='+')
            {
                int x,y,cost;
                scanf("%lld %lld %lld",&x,&y,&cost);
                split(y,x);
                add(x,cost);
            }
            if(s[0]=='/')
            {
                int u,v;
                scanf("%lld %lld",&u,&v);
                split(u,v);
                printf("%lld
    ",sum[v]);
            }
        }
    }
  • 相关阅读:
    1414 冰雕
    1475 建设国家(优先队列)
    Digit Division
    Sleep Buddies
    Reverse and Compare(DP)
    1536 不一样的猜数游戏
    Genealogical tree
    网站日志实时分析工具GoAccess使用
    CentOS下一键安装Openstack
    权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现2
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/9477499.html
Copyright © 2011-2022 走看看