1663: Tree

Time Limit: 5 Sec  Memory Limit:
128 MB

Submit: 26  Solved: 11

[Submit][

id=1663">Status][

pid=1663">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(树链剖分)的更多相关文章

  1. Hdu 5274 Dylans loves tree (树链剖分模板)

    Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...

  2. POJ3237 Tree 树链剖分 边权

    POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...

  3. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

  4. 【BZOJ-4353】Play with tree 树链剖分

    4353: Play with tree Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 31  Solved: 19[Submit][Status][ ...

  5. SPOJ Query on a tree 树链剖分 水题

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  6. poj 3237 Tree 树链剖分

    题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...

  7. Codeforces Round #200 (Div. 1) D Water Tree 树链剖分 or dfs序

    Water Tree 给出一棵树,有三种操作: 1 x:把以x为子树的节点全部置为1 2 x:把x以及他的所有祖先全部置为0 3 x:询问节点x的值 分析: 昨晚看完题,马上想到直接树链剖分,在记录时 ...

  8. poj 3237 Tree 树链剖分+线段树

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  9. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

随机推荐

  1. 使用 SQL Server 的 uniqueidentifier 字段类型

    原文:使用 SQL Server 的 uniqueidentifier 字段类型 SQL Server 自 2008 版起引入了 uniqueidentifier 字段,它存储的是一个 UUID, 或 ...

  2. C语言中<CR>是什么意思

    在文本处理中, CR, LF, CR/LF是不同操作系统上使用的换行符.Dos和windows采用回车+换行CR/LF表示下一行, 而UNIX/Linux采用换行符LF表示下一行,苹果机(MAC OS ...

  3. axure产品原型图,元件库导入方法

    axure是公司产品经理常用的软件,用来绘制产品原型图. 为了画出漂亮的原型图,需要各色各样的元件.因此导入各类元件库很有用处: 打开元件库视图: 载入元件库,选择事先下载好的元件 元件库下载:htt ...

  4. 前端打包利器:webpack工具

    一.什么是WebPack,为什么要使用它? 1.为什要使用WebPack 现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包.为了简化开发的复杂度,前端 ...

  5. python项目构建工具zc.buildout

    转载:http://blog.csdn.net/u011630575/article/details/52940099 buildout简介 Buildout 是一个基于Python的构建工具, Bu ...

  6. Node.js 使用jQuery取得Nodejs http服务端返回的JSON数组示例

    server.js代码: // 内置http模块,提供了http服务器和客户端功能(path模块也是内置模块,而mime是附加模块) var http=require("http" ...

  7. Input.GetAxis 获取轴

    static function GetAxis (axisName : string) : float Description描述 Returns the value of the virtual a ...

  8. 显式启动Activity和隐式启动Activity

    1.显式启动Intent intent = new Intent(this, class);startActivity(intent); 2.隐式启动AndroidManifest.xml中定义某个A ...

  9. Nmon命令行:Linux系统性能的监测利器

    如果你眼下正在寻找一款非常易于使用的Linux性能监测工具,那么我强烈推荐安装和使用Nmon命令行实用工具. Nmon监测工具 Nmon是一款面向系统管理员的调优和基准测量工具,可以用来显示关于下列方 ...

  10. react-native 项目实战 -- 新闻客户端(1) -- 初始化项目结构

    1.在项目根目录新建Componet文件夹(专门用来放我们的自定义组件),里面新建Main.js.Home.js.Message.js.Mine.js.Find.js 2.修改 index.andro ...