zoukankan      html  css  js  c++  java
  • CSU 1663: Tree(树链剖分)

    1663: Tree

    Time Limit: 5 Sec  Memory Limit: 128 MB
    Submit: 26  Solved: 11
    [Submit][Status][Web Board]

    Description

    CSU has a lot of trees. But there is a tree which is different from the others. This one is made of weighted edges and I have three kinds of operations on it:
    1. C a b: Change the weight of edge a to b (1 ≤ b ≤ 100);
    2. M a b c: Multiply the weights of those edges on the path from node a to node b by c (|c|≤10, c ≠ 0);
    3. Q a b: Get the sum of weights from all the edges on the path from node a to node b.

    Input

    There are multiple test cases.
    The first line will contain a positive integer T (T ≤ 10) meaning the number of test cases.
    Each test case will have an integer N (1 ≤ N ≤ 50,000) indicating the number of nodes marked from 1 to N.
    Then N-1 lines followed. Each lines contains three integers a, b and c (1 ≤ a, b, c ≤ N, a ≠ b, 1 ≤ c ≤ 100) indicating the there is an edge connecting node a and node b with weight c. The edges are marked from 1 to N-1 in the order of appearance.
    Then some operations followed, with one operation per line. The format is as shown in the problem description. A single letter ‘E’ indicates the end of the case. There are no more than 50,000 operations per test case.

    Output

    For each ‘Q’ operation, output an integer meaning the sum. The final result will never exceed 32-bit signed integer.

    Sample Input

    2
    4
    1 2 14
    1 3 20
    3 4 1
    C 3 11
    M 1 4 3
    M 3 4 2
    M 1 3 2
    Q 2 4
    M 1 4 -1
    M 3 4 -2
    Q 2 4
    E
    3
    1 2 4
    1 3 2
    Q 2 3
    C 1 7
    M 2 3 2
    M 1 3 5
    Q 2 3
    E
    

    Sample Output

    200
    26
    6
    34
    
    #include<stdio.h> 
    #include<string.h> 
    #define LL long long 
    const int N = 50005; 
      
    int head[N<<1],to[N<<1],next1[N<<1],tot; 
    int deep[N],fath[N],son[N],num[N]; 
    int top[N],p[N],pos; 
      
    void init(){ 
        pos=tot=0; 
        memset(head,-1,sizeof(head)); 
    } 
    void addEdge(const int& u, const int& v){ 
        to[tot] = v, next1[tot] = head[u], head[u] = tot++; 
    } 
    void addUndirEdge(const int& u, const int& v){ 
        addEdge(u, v), addEdge(v, u); 
    } 
      
    void dfs1(int u,int pre,int d){ 
         fath[u]=pre; 
         deep[u]=d; 
         son[u]=-1; 
         num[u]=1; 
         for(int i=head[u]; i!=-1; i=next1[i]){ 
             int v=to[i]; 
             if(v==fath[u])continue; 
             dfs1(v,u,d+1); 
             num[u]+=num[v]; 
             if(son[u]==-1||num[v]>num[son[u]]) 
                son[u]=v; 
         } 
    } 
    void getpos(int u,int root){ 
        top[u]=root; 
        p[u]=pos++; 
        if(son[u]==-1) 
            return ; 
        getpos(son[u],root); 
        for(int i=head[u]; i!=-1; i=next1[i]){ 
            int v=to[i]; 
            if(v==son[u]||v==fath[u]) 
                continue; 
            getpos(v,v); 
        } 
    } 
    struct TREE{ 
        LL milt,sum; 
    }root[N*3]; 
    LL cost[N]; 
      
    void pushUp(int k){ 
        root[k].sum=root[k<<1].sum+root[k<<1|1].sum; 
    } 
    void pushDow(int k){ 
        if(root[k].milt!=1) 
        { 
            root[k<<1].sum*=root[k].milt; 
            root[k<<1].milt*=root[k].milt; 
      
            root[k<<1|1].sum*=root[k].milt; 
            root[k<<1|1].milt*=root[k].milt; 
            root[k].milt=1; 
        } 
    } 
    void build(int l, int r, int k){ 
        root[k].milt=1; 
        if(l==r){ 
            root[k].sum=cost[l]; return ; 
        } 
        int mid=(l+r)>>1; 
        build(l,mid,k<<1); 
        build(mid+1,r,k<<1|1); 
        pushUp(k); 
    } 
    void update_C(int l, int r, int k, const int& id, LL c){ 
        if(l==r){ 
            root[k].sum=c; return ; 
        } 
        int mid=(l+r)>>1; 
        pushDow(k); 
        if(id<=mid) 
            update_C(l,mid,k<<1,id,c); 
        else
            update_C(mid+1,r,k<<1|1,id,c); 
        pushUp(k); 
    } 
    void updata_M(int l,int r,int k,int L,int R,int M){ 
        if(L<=l&&r<=R){ 
            root[k].milt*=M; root[k].sum*=M; 
            return ; 
        } 
        pushDow(k); 
        int mid=(l+r)>>1; 
        if(L<=mid) 
         updata_M(l,mid,k<<1,L,R,M); 
         if(mid<R) 
         updata_M(mid+1,r,k<<1|1,L,R,M); 
         pushUp(k); 
    } 
    LL query(int l, int r, int k, const int& L, const int& R){ 
        if(L<=l&&r<=R){ 
            return root[k].sum; 
        } 
        pushDow(k); 
        int mid=(l+r)>>1; 
        LL sum=0; 
        if(L<=mid) 
            sum+=query(l,mid,k<<1,L,R); 
        if(mid<R) 
            sum+=query(mid+1,r,k<<1|1,L,R); 
        return sum; 
    } 
    void swp(int &u,int &v){ 
        int tt=u; u=v; v=tt; 
    } 
    LL solve(int u,int v,int flag,LL M){ 
        int fu=top[u], fv=top[v]; 
        LL sum=0; 
        while(fu!=fv){ 
            if(deep[fu]<deep[fv]){ 
                swp(fu,fv); swp(u,v); 
            } 
            if(flag==0) 
             updata_M(1,pos,1,p[fu],p[u],M); 
            else
            sum+=query(1,pos,1,p[fu],p[u]); 
            u=fath[fu]; fu=top[u]; 
        } 
        if(u==v)return sum; 
        if(deep[u]>deep[v]) 
            swp(u,v); 
        if(flag==0) 
            updata_M(1,pos,1,p[son[u]],p[v],M); 
        else
            sum+=query(1,pos,1,p[son[u]],p[v]);//一不小心p[son[u]]写成了p[u]让我WA了好几次(求边权用p[son[u]],求点权用p[u]) 
        return sum; 
    } 
      
    struct EDG{ 
        int u,v; 
        LL c; 
    }edg[N]; 
      
    int main() 
    { 
        int n,m,a,b,T; 
        char op[10]; 
        scanf("%d",&T); 
        while(T--){ 
            scanf("%d",&n); 
            init(); 
            for(int i=1; i<n; i++){ 
                scanf("%d%d%lld",&edg[i].u,&edg[i].v,&edg[i].c); 
                addUndirEdge(edg[i].u, edg[i].v); 
            } 
            dfs1(1,1,1); 
            getpos(1,1); 
            for(int i=1; i<n; i++){ 
                if(deep[edg[i].u]>deep[edg[i].v]) 
                    swp(edg[i].u, edg[i].v); 
                cost[p[edg[i].v]]=edg[i].c; 
            } 
            pos=n; 
            build(1,pos,1); 
      
            while(1){ 
                scanf("%s",op); 
                if(op[0]=='E') 
                    break; 
                scanf("%d%d",&a,&b); 
                if(op[0]=='C') 
                    update_C(1,pos,1,p[edg[a].v],b); 
                else if(op[0]=='M'){ 
                    LL M; 
                    scanf("%lld",&M); 
                    solve(a,b,0,M); 
                } 
                 else
                    printf("%lld
    ",solve(a,b,1,1)); 
            } 
        } 
      
    } 
      
    /************************************************************** 
        Problem: 1663 
        User: aking2015 
        Language: C++ 
        Result: Accepted 
        Time:2696 ms 
        Memory:9044 kb 
    ****************************************************************/


  • 相关阅读:
    单例模式
    C++中迭代器原理、失效和简单实现
    C++中静态成员变量要在类外部再定义或初始化的原因
    idea maven javaweb项目迁移时的maven和版本报错问题解决(可解决同类错误)
    java 继承类之后,访问不到超类的属性的原因及解决方法
    spring boot admin
    javaweb 报表生成(pdf excel)所需要用到的技术和思路
    团队合作开发git冲突解决方案 Intellij IDEA
    【项目管理】 使用IntelliJ IDEA 将项目发布(提交)到GitLab
    IDEA/Git 设置多个push远程仓库或者同时提交多个push仓库
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/7223839.html
Copyright © 2011-2022 走看看