• BZOJ2631: tree


    题解: LCT 类似维护一次函数 a*x+b 的双标记

    /**************************************************************
        Problem: 2631
        User: c20161007
        Language: C++
        Result: Accepted
        Time:21336 ms
        Memory:9352 kb
    ****************************************************************/
     
    #include <iostream>
    #include <cstdio>
    #include <vector>
    #define ll  unsigned int
    const int MAXN=1e5+10;
    const int lth=51061;
    using namespace std;
    //ll readll(){
    //    ll x=0,f=1;char ch=getchar();
    //    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    //    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    //    return x*f;
    //}
    int readint(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    int ch[MAXN][2],pre[MAXN],rt[MAXN],size[MAXN],n,q;
    ll key[MAXN],sum[MAXN],add[MAXN],res[MAXN],mul[MAXN];
    void Treavel(int x)
    {
        if(x)
        {
        //  cout<<x<<endl;
            Treavel(ch[x][0]);
            printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d
    ",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]);
            Treavel(ch[x][1]);
        }
    }
    void debug(int rp)
    {
        printf("root:%d
    ",rp);
        Treavel(rp);
    }
    void update(int r,ll vul1,ll vul2){
        if(!r) return ;
        sum[r]=((sum[r]*vul1)%lth+(size[r]*vul2)%lth)%lth;
        key[r]=((vul1*key[r])%lth+vul2)%lth;
        mul[r]=(mul[r]*vul1)%lth;
        add[r]=((add[r]*vul1)%lth+vul2)%lth;
    }
    void update_add(int r,ll vul){
        if(!r) return ;
        key[r]=(vul+key[r])%lth;
        sum[r]=(sum[r]+1ll*size[r]*vul)%lth;
        add[r]=(add[r]+vul)%lth;
    }
    void update_mul(int r,ll vul){
        if(!r) return ;
        key[r]=(key[r]*vul)%lth;
        sum[r]=(sum[r]*vul)%lth;
        mul[r]=(mul[r]*vul)%lth;
        add[r]=(add[r]*vul)%lth;
    }
    void update_res(int r){
        if(!r) return ;
        swap(ch[r][0],ch[r][1]);
        res[r]^=1;
    }
    void push(int x){
        if(res[x]){
            update_res(ch[x][0]);
            update_res(ch[x][1]);
            res[x]^=1;
        }
        update(ch[x][0],mul[x],add[x]);
        update(ch[x][1],mul[x],add[x]);
        mul[x]=1,add[x]=0;
    }
    void up(int x){
        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
        sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+key[x])%lth;
    }
    void P(int r){
        if(!rt[r]) P(pre[r]);
        push(r);
    }
    void rotate(int x,int kind){
        int y=pre[x];
        ch[y][!kind]=ch[x][kind];
        pre[ch[x][kind]]=y;
        if(rt[y]) rt[y]=0,rt[x]=1;
        else ch[pre[y]][ch[pre[y]][1]==y]=x;
        pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
        up(y);
    }
    void splay(int x){
        P(x);
        //cout<<x<<"-----"<<rt[x]<<endl;
        while(!rt[x]){
            if(rt[pre[x]]) rotate(x,ch[pre[x]][0]==x);
            else{
                int y=pre[x];int kind=ch[pre[y]][0]==y;
                if(ch[y][kind]==x) rotate(x,!kind),rotate(x,kind);
                else rotate(y,kind),rotate(x,kind); 
            }
        }
        up(x);
    }
    void access(int x){
        int y=0;
        //cout<<x<<endl;
        //cout<<pre[1]<<"-----"<<endl;
    //  cout<<x<<" "<<pre[x]<<endl;
        while(x){
            splay(x);
            //debug(x);
            //cout<<x<<"------"<<y<<endl;
            if(ch[x][1]) rt[ch[x][1]]=1,pre[ch[x][1]]=x,ch[x][1]=0;
            ch[x][1]=y;
            up(x);
            if(y) rt[y]=0,pre[y]=x;
            y=x;x=pre[x];
        //  cout<<x<<" "<<y<<endl;
        }
        //debug(1);
        return ;
    }
    void mroot(int x){
        access(x);//debug(x);
        splay(x);//debug(x);
        //cout<<pre[1]<<"====="<<endl;
        //debug(x);
        update_res(x);
        //up(x);
        return ;
    }
    void operator_add(int u,int v,ll vul){
        mroot(u);access(v);splay(u);
        update_add(u,vul);
        return ;
    }
    void operator_chong(int u1,int v1,int u2,int v2){
        mroot(u1);access(v1);splay(v1);
        ch[v1][0]=0;up(v1);
        pre[u1]=pre[v1]=0;rt[u1]=rt[v1]=1;
        mroot(u2);pre[u2]=v2;
    }
    void operator_mul(int u,int v,ll vul){
        //cout<<u<<" "<<v<<endl;
    //  cout<<u<<" "<<v<<" "<<pre[u]<<" "<<pre[v]<<endl;
    //  debug(u);debug(v);
        mroot(u);
        //debug(u);
    //  cout<<rt[v]<<endl;
        access(v);//debug(v);
        splay(u);
        update_mul(u,vul);
    }
    int operator_querty(int u,int v){
        //cout<<pre[u]<<" "<<pre[v]<<endl;
        //if(u==v) return key[u]%lth;
        mroot(u);//debug(u);
        //cout<<pre[1]<<"------"<<endl;
        access(v);//debug(v);
        splay(u);
    //  debug(u);
        return sum[u]%lth;
    }
    vector<int>vec[MAXN];
    void dfs(int v,int fa){
        pre[v]=fa;
        for(int i=0;i<vec[v].size();i++){
            if(vec[v][i]!=fa) dfs(vec[v][i],v);
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        n=readint();q=readint();
        for(int i=1;i<=n;i++){
            ch[i][0]=ch[i][1]=pre[i]=add[i]=res[i]=0;
            size[i]=rt[i]=key[i]=sum[i]=mul[i]=1;
        }
        char ch;int u,v,u1,v1;ll x;
        for(int i=1;i<n;i++){
            u=readint();v=readint();
            vec[u].push_back(v);vec[v].push_back(u);
        }
        dfs(1,0);
        for(int i=1;i<=q;i++){
            scanf(" %c",&ch);u=readint();v=readint();
            if(ch=='+'){
                scanf("%d
    ",&x);operator_add(u,v,x%lth);
            }
            else if(ch=='-'){
                scanf("%d
    ",&u1);scanf("%d
    ",&v1);
                operator_chong(u,v,u1,v1);
            }
            else if(ch=='*'){
                scanf("%d
    ",&x);
                operator_mul(u,v,x%lth);
            }
            else printf("%d
    ",operator_querty(u,v));
        }
        return 0;
    }
    
    

    2631: tree

    Time Limit: 30 Sec  Memory Limit: 128 MB
    Submit: 5381  Solved: 1811
    [Submit][Status][Discuss]

    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

  • 相关阅读:
    Fragment+ViewPager实现仿微信点击和滑动切换界面
    Android:控件WebView显示网页
    Android:控件WebView显示网页
    蓝桥杯 算法训练 数字三角形
    蓝桥杯 算法训练 数字三角形
    [置顶] Netty学习总结(1)——Netty入门介绍
    Git学习总结(7)——Git GUI学习教程
    Linux学习总结(12)——Linux必须学会的60个命令
    程序猿学习资料集
    Spring学习总结(14)——Spring10种常见异常解决方法
  • 原文地址:https://www.cnblogs.com/wang9897/p/9461695.html
Copyright © 2020-2023  润新知