CSU 1663: Tree(树链剖分)
1663: Tree
Time Limit: 5 Sec Memory Limit: id=1663">Status pid=1663">Web
128 MB
Submit: 26 Solved: 11
[Submit][
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(树链剖分)的更多相关文章
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
- 【BZOJ-4353】Play with tree 树链剖分
4353: Play with tree Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 31 Solved: 19[Submit][Status][ ...
- SPOJ Query on a tree 树链剖分 水题
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- poj 3237 Tree 树链剖分
题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...
- Codeforces Round #200 (Div. 1) D Water Tree 树链剖分 or dfs序
Water Tree 给出一棵树,有三种操作: 1 x:把以x为子树的节点全部置为1 2 x:把x以及他的所有祖先全部置为0 3 x:询问节点x的值 分析: 昨晚看完题,马上想到直接树链剖分,在记录时 ...
- poj 3237 Tree 树链剖分+线段树
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- 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 ...
随机推荐
- 什么是IIS并发连接数
http://blog.csdn.net/leftfist/article/details/38407223 https://wk.baidu.com/view/2962d073f242336c1e ...
- iOS教程:如何使用Core Data – 预加载和引入数据
这是接着上一次<iOS教程:Core Data数据持久性存储基础教程>的后续教程,程序也会使用上一次制作完成的. 再上一个教程中,我们只做了一个数据模型,之后我们使用这个数据模型中的数据创 ...
- 粗谈CDN
CDN:内容分发网络(content delivery network) 1.DNS解析到最快(有可能是地理上最近,也有可能是地理上远但是链路最好)的CDN缓存设备 2.从CDN获取已经缓存的资源 3 ...
- json格式在线解析
地址:https://www.bejson.com/ { "PN": "123456", "DomainName": ".gxyc ...
- Spark Streaming与Storm的对比及使用场景
Spark Streaming与Storm都可以做实时计算,那么在做技术选型的时候到底应该选择哪个呢?通过下图可以从计算模型.计算延迟.吞吐量.事物.容错性.动态并行度等方方面进行对比. 对比点 ...
- Linq 数据排序,分页
在用Linq查询中,常常需要用到分页功能,因为每次都需要些分页这些功能,于是把分页功能提取出来,不喜大家勿喷,只是贴出来,自觉地很实用.一下贴出核心代码: /// <summary> // ...
- Time.timeScale 时间缩放
static var timeScale : float Description描述 The scale at which the time is passing. This can be used ...
- Codeforces Round #262 (Div. 2)解题报告
详见:http://robotcator.logdown.com/posts/221514-codeforces-round-262-div-2 1:A. Vasya and Socks http ...
- Cache和Buffer的区别(转载)
1. Cache:缓存区,是高速缓存,是位于CPU和主内存之间的容量较小但速度很快的存储器,因为CPU的速度远远高于主内存的速度,CPU从内存中读取数据需等待很长的时间,而 Cache保存着CPU刚 ...
- HDU-1047-Integer Inquiry(Java大数水题 && 格式恶心)
Integer Inquiry Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...