题意:给定一棵树,告诉了每条边的权值,然后给出两种操作:
(1)把第i条边的权值改为val
(2)询问a,b路径上权值最大的边
分析:本题与HDU3966差不多,区别就是:HDU3966是告诉树中点权的值,这里是边权。
所以我们可以转化,用边的孩子节点来表示该边。
#include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> using namespace std; const int N=50010; const int INF=1<<30; int n,tim; int num[N],siz[N],top[N],son[N]; int dep[N],tid[N],rank[N],fa[N]; int head[N],to[2*N],next[2*N],w[2*N],edge; struct Edge { int u,v,c; }; Edge tmp[2*N]; void Init() { memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); tim=0; edge=0; } void addedge(int u,int v,int c) { to[edge]=v,w[edge]=c,next[edge]=head[u],head[u]=edge++; to[edge]=u,w[edge]=c,next[edge]=head[v],head[v]=edge++; } //树链剖分部分 void dfs1(int u,int father,int d) { dep[u]=d; fa[u]=father; siz[u]=1; for(int i=head[u]; ~i; i=next[i]) { int v=to[i]; if(v!=father) { dfs1(v,u,d+1); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } } } void dfs2(int u,int tp) { top[u]=tp; tid[u]=++tim; rank[tid[u]]=u; if(son[u]==-1) return; dfs2(son[u],tp); for(int i=head[u]; ~i; i=next[i]) { int v=to[i]; if(v!=son[u]&&v!=fa[u]) dfs2(v,v); } } //线段树部分 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 int MAX[4*N]; void PushUP(int rt) { MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]); } void Build(int l,int r,int rt) { if(l==r) { MAX[rt]=num[l]; return; } int mid=(l+r)>>1; Build(lson); Build(rson); PushUP(rt); } void Update(int l,int r,int rt,int p,int val) { if(l==r) { MAX[rt]=val; return; } int mid=(l+r)>>1; if(p<=mid) Update(lson,p,val); else Update(rson,p,val); PushUP(rt); } int Query(int l,int r,int rt,int L,int R) { if(L<=l&&R>=r) return MAX[rt]; int mid=(l+r)>>1; int ret=-INF; if(L<=mid) ret=max(ret,Query(lson,L,R)); if(R>mid) ret=max(ret,Query(rson,L,R)); return ret; } void Change(int x,int val) { if(dep[tmp[x].u]>dep[tmp[x].v]) Update(2,n,1,tid[tmp[x].u],val); else Update(2,n,1,tid[tmp[x].v],val); } int query(int x,int y) { int ans=-INF; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); ans=max(ans,Query(2,n,1,tid[top[x]],tid[x])); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); if(x!=y) ans=max(ans,Query(2,n,1,tid[x]+1,tid[y])); return ans; } int main() { char oper[15]; int a,b,c,t; scanf("%d",&t); while(t--) { Init(); scanf("%d",&n); for(int i=1; i<n; i++) { scanf("%d%d%d",&a,&b,&c); tmp[i].u=a;tmp[i].v=b;tmp[i].c=c; addedge(a,b,c); } dfs1(1,1,1); dfs2(1,1); //用边的孩子节点来表示该边 for(int i=1;i<n;i++) { if(dep[tmp[i].u]>dep[tmp[i].v]) num[tid[tmp[i].u]]=tmp[i].c; else num[tid[tmp[i].v]]=tmp[i].c; } Build(2,n,1); while(1) { scanf("%s",oper); if(oper[0]=='D') break; scanf("%d%d",&a,&b); if(oper[0]=='Q') printf("%d\n",query(a,b)); else Change(a,b); } } return 0; }