zoukankan      html  css  js  c++  java
  • 【BZOJ】2631: tree LCT

    【题意】给定n个点的树,每个点初始权值为1,m次操作:1.x到y的点加值,2.断一条边并连一条边,保证仍是树,3.x到y的点乘值,4.x到y的点权值和取模。n,m<=10^5。

    【算法】Link-Cut Tree

    【题解】区间加和区间乘标记的处理:【BZOJ】1798: [Ahoi2009]Seq 维护序列seq 线段树

    splay上维护要注意:

    1.上传时加本身。

    2.改值的时候不能影响到0点。

    3.所有改变点的儿子的地方都要上传,所有改变点的父亲的地方都要下传。

    除了rotate,还有access的时候要上传up。

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #define int unsigned int
    using namespace std;
    int read(){
        int s=0,t=1;char c;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s*t;
    }
    const int maxn=100010,MOD=51061;
    int n,Q,sum[maxn],A[maxn],B[maxn],g[maxn],a[maxn],sz[maxn],t[maxn][2],f[maxn],N[maxn];
    int M(int x){return x>=MOD?x-MOD:x;}
    void up(int x){sum[x]=M(M(sum[t[x][0]]+sum[t[x][1]])+a[x]);sz[x]=sz[t[x][0]]+sz[t[x][1]]+1;}
    void modify_a(int k,int x){
        if(!k)return;
        a[k]=M(a[k]+x);
        sum[k]=M(sum[k]+sz[k]*x%MOD);
        A[k]=M(A[k]+x);
    }//make 0 no influence
    void modify_b(int k,int x){
        if(!k)return;
        a[k]=a[k]*x%MOD;
        sum[k]=sum[k]*x%MOD;A[k]=A[k]*x%MOD;B[k]=B[k]*x%MOD;
    }
    void down(int k){
        if(g[k]){
            swap(t[k][0],t[k][1]);
            if(t[k][0])g[t[k][0]]^=1;
            if(t[k][1])g[t[k][1]]^=1;
            g[k]=0;
        }
        if(B[k]!=1){
            modify_b(t[k][0],B[k]);modify_b(t[k][1],B[k]);
            B[k]=1;
        }
        if(A[k]){
            modify_a(t[k][0],A[k]);modify_a(t[k][1],A[k]);
            A[k]=0;
        }
    }
    bool isroot(int x){return !x||(t[f[x]][0]!=x&&t[f[x]][1]!=x);}
    void rotate(int y){
        int x=f[y];
        int k=y==t[x][0];
        t[x][!k]=t[y][k];f[t[y][k]]=x;
        if(!isroot(x))t[f[x]][x==t[f[x]][1]]=y;f[y]=f[x];f[x]=y;
        t[y][k]=x;
        up(x);up(y);
    }
    void splay(int x){
        int top=x,tot=1;N[1]=x;
        while(!isroot(top))top=f[top],N[++tot]=top;
        for(int i=tot;i>=1;i--)down(N[i]);
        while(!isroot(x)){
            if(isroot(f[x])){rotate(x);break;}
            int X=x==t[f[x]][1],Y=f[x]==t[f[f[x]]][1];
            if(X^Y)rotate(x),rotate(x);
            else rotate(f[x]),rotate(x);
        }
    }
    void access(int x){
        int y=0;
        while(x){
            splay(x);
            t[x][1]=y;
            up(x);///
            y=x;x=f[x];
        }
    }
    void reserve(int x){access(x);splay(x);g[x]^=1;}
    void link(int x,int y){reserve(x);f[x]=y;}
    void find(int x,int y){reserve(x);access(y);splay(y);}
    void cut(int x,int y){find(x,y);t[y][0]=f[x]=0;}
    
    char s[10];
    #undef int
    int main(){
    #define int unsigned int
        n=read();Q=read();
        for(int i=1;i<=n;i++)sum[i]=a[i]=1,sz[i]=1,A[i]=0,B[i]=1;
        for(int i=1;i<n;i++)link(read(),read());
        while(Q--){
            scanf("%s",s);
            int x=read(),y=read();
            if(s[0]=='+'){
                int z=read();
                find(x,y);modify_a(y,z);
            }
            if(s[0]=='-'){
                int u=read(),v=read();
                cut(x,y);link(u,v);
            }
            if(s[0]=='*'){
                int z=read();
                find(x,y);modify_b(y,z);
            }
            if(s[0]=='/'){
                find(x,y);printf("%d
    ",sum[y]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    JAVA设计模式---总述篇
    Java中对象创建时的内存分配
    for循环打印空心菱形的新方法
    springcloud2.X通过actuator加载配置无效问题
    golang-错误处理
    golang-字符串
    golang-方法和接口
    golang-结构体与指针
    golang-数组、切片、映射
    golang-流程控制
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8493890.html
Copyright © 2011-2022 走看看