Status][pid=1663">WebBoard]DescriptionCSUhasalotoftrees.Butthereisatreewhichisdifferentfromtheothers"/>

CSU 1663: Tree(树链剖分)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSU 1663: Tree(树链剖分)相关的知识,希望对你有一定的参考价值。

1663: Tree

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 26  Solved: 11
[Submit][php?

id=1663">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\n",solve(a,b,1,1)); 
        } 
    } 
  
} 
  
/************************************************************** 
    Problem: 1663 
    User: aking2015 
    Language: C++ 
    Result: Accepted 
    Time:2696 ms 
    Memory:9044 kb 
****************************************************************/


以上是关于CSU 1663: Tree(树链剖分)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3237 Tree(树链剖分)

POJ 3723 Tree(树链剖分)

hdu 5044 Tree (树链剖分+标记数组)

Codeforces 343D Water Tree & 树链剖分教程

poj 3237 Tree(树链剖分,线段树)

hdu6547Tree(树链剖分, 线段树区间根号)