1607: Do You Have The Template?
Time Limit: 7 Sec Memory Limit: 128 MBSubmit: 112 Solved: 8
[ Submit][ Status][ Web Board]
Description
There is a tree with N vertices, each edges have a positive length.
And here comes 4 operations,
0 a b, means query the maximum length and the sum of length on the path between vertex a and vertex b.
1 a b, means change the a-th edge's length to b.
2 a b 0 c, means change all edges' length on the path between vertex a and vertex b to c.
2 a b 1 c, means add all edges' length on the path between vertex a and vertex b by c.
Input
There're several cases.
The first line contains a positive integer N (2 <= N <= 10000), meaning there're N vertices, marked 1 to N. Then N – 1 lines follow with the i-th line describing the i-th edge. Each line contains three integers a b c, meaning there is an edge between vertex a and vertex b with the length of c.
Then one integer M (M <= 10000), means there're M queries. And followed by M lines, each line will contain one operation described as above.
Output
For each 0 a b query, you should output the maximum length and the sum.
The data insure no number will be bigger than 2^31.
Sample Input
4
1 2 1
2 3 2
2 4 3
10
0 1 3
0 1 4
0 3 4
1 2 3
0 1 3
2 4 3 0 2
0 1 4
2 4 3 1 2
0 1 3
0 1 4
Sample Output
2 3
3 4
3 5
3 4
2 3
4 5
4 5
题意:给出一棵树有n个节点,每个边有权值,现在有M个操作:
0 a b 表示输出从a点到b点的路径的边权最大值和边树总和。
1 a b 表示第a条边的权值变为b
2 a b 0 c 表示从a点到b点的路径的每条边权都变成c
2 a b 1 c 表示从a点到b点的路径的每条边权都加上c
坑点:在CSU的这道题用vector建图就WA。标程代码有漏洞,就是用root[k].toc去判断是否需要更新线段树中k的左右子节点。
解题:用树链剖分,边权变点权。用线段树去维护边权。
#include<stdio.h> #include<string.h> #include<vector> const int N=10015; using namespace std; int head[N], to[N << 1], next1[N << 1], tot; int top[N]; //top[v]=u表示点v,u在一个链中,且u是这个链深度最小的点(即顶端) int fath[N]; //记录父节点 int deep[N]; //每个点在树上的深度 int num[N]; //每棵子树的节点个数 int son[N]; //选的重边子节点 int p[N]; //树上每个点在线段树中所对应的点 int pos; 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 init(int n) { pos=0; tot=0; memset(son,-1,sizeof(son)); memset(head,-1,sizeof(head)); } void dfs1(int u,int pre,int d) { deep[u]=d; fath[u]=pre; num[u]=1; for (int i = head[u]; i != -1; i = next1[i]) { int v = to[i]; if(v==pre)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(son[u]!=v&&v!=fath[u]) getpos(v,v); } } //线段树 struct tree { int sum,maxv,toc,addc; }root[N*4]; int val[N]; int MAX(int a,int b) { return a>b?a:b; } void build(int l,int r,int k) { int mid=(l+r)/2; root[k].addc=0; root[k].toc=0; if(l==r){ root[k].sum=root[k].maxv=val[l]; return ; } build(l,mid,k<<1); build(mid+1,r,k<<1|1); root[k].sum=root[k<<1].sum+root[k<<1|1].sum; root[k].maxv=MAX(root[k<<1].maxv,root[k<<1|1].maxv); } void upson(int k,int l,int r) { int mid=(l+r)/2; if(root[k].toc) { root[k<<1].sum=(mid-l+1)*root[k].toc; root[k<<1].maxv=root[k].toc; root[k<<1].toc=root[k].toc; root[k<<1].addc=0; root[k<<1|1].sum=(r-mid)*root[k].toc; root[k<<1|1].maxv=root[k].toc; root[k<<1|1].toc=root[k].toc; root[k<<1|1].addc=0; root[k].toc=0; } if(root[k].addc) { root[k<<1].sum+=(mid-l+1)*root[k].addc; root[k<<1].maxv+=root[k].addc; root[k<<1].addc+=root[k].addc; root[k<<1|1].sum+=(r-mid)*root[k].addc; root[k<<1|1].maxv+=root[k].addc; root[k<<1|1].addc+=root[k].addc; root[k].addc=0; } } void updata1(int l,int r,int k,const int L,const int R,int c) { if(L<=l&&r<=R) { root[k].sum=(r-l+1)*c; root[k].maxv=c; root[k].toc=c; root[k].addc=0; return ; } int mid=(l+r)/2; upson(k,l,r); if(L<=mid) updata1(l,mid,k<<1,L,R,c); if(mid<R) updata1(mid+1,r,k<<1|1,L,R,c); root[k].sum=root[k<<1].sum+root[k<<1|1].sum; root[k].maxv=MAX(root[k<<1].maxv,root[k<<1|1].maxv); } void updata2(int l,int r,int k, int L, int R,int c) { if(L<=l&&r<=R) { root[k].sum+=(r-l+1)*c; root[k].maxv+=c; root[k].addc+=c; return ; } int mid=(l+r)/2; upson(k,l,r); if(L<=mid) updata2(l,mid,k<<1,L,R,c); if(mid<R) updata2(mid+1,r,k<<1|1,L,R,c); root[k].sum=root[k<<1].sum+root[k<<1|1].sum; root[k].maxv=MAX(root[k<<1].maxv,root[k<<1|1].maxv); } int sum,maxv; void query(int l,int r,int k,int L,int R) { if(L<=l&&r<=R) { sum+=root[k].sum; maxv=MAX(maxv,root[k].maxv); return ; } int mid=(l+r)/2; upson(k,l,r); if(L<=mid) query(l,mid,k<<1,L,R); if(mid<R) query(mid+1,r,k<<1|1,L,R); } void swp(int &a,int &b) { int tt; tt=a; a=b; b=tt; } void Operat0(int u,int v) { int f1=top[u], f2=top[v]; sum=0; maxv=0; while(f1!=f2) { if(deep[f1]<deep[f2]) { swp(f1,f2); swp(u,v); } query(1,pos,1,p[f1],p[u]); u=fath[f1]; f1=top[u]; } if(u==v) return ; if(deep[u]>deep[v])swp(u,v); query(1,pos,1,p[son[u]],p[v]); } void Operat1(int u,int v,int c) { int f1=top[u], f2=top[v]; while(f1!=f2) { if(deep[f1]<deep[f2]) { swp(f1,f2); swp(u,v); } updata1(1,pos,1,p[f1],p[u],c); u=fath[f1]; f1=top[u]; } if(u==v) return ; if(deep[u]>deep[v])swp(u,v); updata1(1,pos,1,p[son[u]],p[v],c); } void Operat2(int u,int v,int c) { int f1=top[u], f2=top[v]; while(f1!=f2) { if(deep[f1]<deep[f2]) { swp(f1,f2); swp(u,v); } updata2(1,pos,1,p[f1],p[u],c); u=fath[f1]; f1=top[u]; } if(u==v) return ; if(deep[u]>deep[v])swp(u,v); updata2(1,pos,1,p[son[u]],p[v],c); } struct EDG { int u,v,c; }edg[N]; int main() { int n,q,op,a,b; while(scanf("%d",&n)!=EOF) { init(n); for(int i=1;i<n;i++) { scanf("%d%d%d",&edg[i].u,&edg[i].v,&edg[i].c); addUndirEdge(edg[i].u, edg[i].v); } dfs1(1,1,1); getpos(1,1); pos=n; for(int i=1;i<n;i++) { if(deep[edg[i].u]>deep[edg[i].v]) edg[i].v=edg[i].u; val[p[edg[i].v]]=edg[i].c; } build(1,pos,1); scanf("%d",&q); while(q--) { scanf("%d%d%d",&op,&a,&b); if(op==0) { Operat0(a,b); printf("%d %d\n",maxv,sum); } else if(op==1) updata1(1,pos,1,p[edg[a].v],p[edg[a].v],b); else { int tt,c; scanf("%d%d",&tt,&c); if(tt==0) Operat1(a,b,c); else Operat2(a,b,c); } } } } /************************************************************** Problem: 1607 User: aking2015 Language: C++ Result: Accepted Time:912 ms Memory:2180 kb ****************************************************************/