CSU 1663: Tree(树链剖分)
来源:互联网 发布:matlab离散数据求导 编辑:程序博客网 时间:2024/06/08 09:44
1663: Tree
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 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
241 2 141 3 203 4 1C 3 11M 1 4 3M 3 4 2M 1 3 2Q 2 4M 1 4 -1M 3 4 -2Q 2 4E31 2 41 3 2Q 2 3C 1 7M 2 3 2M 1 3 5Q 2 3E
Sample Output
20026634
#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(树链剖分)
- CSU 1811 Tree Intersection
- CSU 1811 Tree Intersection
- csu 1837: Tree Count
- CSU 1414: Query on a Tree
- CSU 1811 Tree Intersection(启发式合并)
- CSU 1811 Tree Intersection(启发式合并)
- CSU-ACM 1005: Binary Search Tree analog
- CSU-1837 Tree Count(树的同构)
- CSU 1005: Binary Search Tree analog
- CSU 1811 Tree Intersection(莫队算法)
- CSU 1805 Tree Capitals(Matrix-Tree定理+Best定理)
- CSU
- CSU
- CSU
- CSU
- CSU
- CSU
- 这题实在不知道起啥名好了
- Mac OS X 系统配置 Apache+MySql+PHP 详细教程
- eclipse java文件 不提示代码
- String.xml
- 压缩文件bzip2 bzcat
- CSU 1663: Tree(树链剖分)
- Asp.net弹出消息对话框
- Why outdoor education for kids matters
- Memcached 集群架构方面的问题
- ******Android应用实例之有道辞典(WebView) **********
- C# 相对路径指定详解
- 【Unity3d】如何开发Unity自动化补丁工具
- 关于对linux磁盘 分区 挂载的最新认识
- const的用法