树链剖分
把边权的模板也敲了一下
关键在于弄明白点和边的对应关系
#include<stdio.h> #include<string.h> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<math.h> using namespace std; #define out(x) cout<<#x<<": "<<x<<endl const double eps(1e-8); const int maxn=10100; const long long inf=-1u>>1; typedef long long ll; int n,e[maxn][3],tot,pos; int deep[maxn],fa[maxn],num[maxn],son[maxn]; int top[maxn],p[maxn],fp[maxn]; struct Edge{ int v,next; }edge[maxn<<1]; int head[maxn]; void addedge(int u,int v){ edge[tot].v=v; edge[tot].next=head[u]; head[u]=tot++; } void dfs1(int u,int pre,int d){//求fa、num、son和deep deep[u]=d; fa[u]=pre; num[u]=1; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; 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 sp){//sp用于求top,并求对应位置 top[u]=sp; p[u]=pos++; fp[p[u]]=u; if(son[u]==-1) return; getpos(son[u],sp); for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fa[u]||v==son[u]) continue; getpos(v,v); } } struct Node{ int l,r,max; }t[maxn<<2]; void build(int p,int l,int r){ t[p].l=l; t[p].r=r; t[p].max=0; if(l==r) return; int mid=(l+r)>>1; build(p<<1,l,mid); build((p<<1)|1,mid+1,r); } void update(int p,int k,int val){ if(t[p].l==k&&k==t[p].r) { t[p].max=val; return; } int mid=(t[p].l+t[p].r)>>1; if(k<=mid) update(p<<1,k,val); else update((p<<1)|1,k,val); t[p].max=max(t[p<<1].max,t[(p<<1)|1].max); } int query(int p,int l,int r){ if(t[p].l==l&&t[p].r==r){ return t[p].max; } int mid=(t[p].l+t[p].r)>>1; if(r<=mid) return query(p*2,l,r); else if(l>mid) return query(p*2+1,l,r); else return max(query(p*2,l,mid),query(p*2+1,mid+1,r)); } void init() { tot=0; pos=0; memset(son,-1,sizeof(son)); memset(head,-1,sizeof(head)); scanf("%d",&n); for(int i=0;i<n-1;i++){ scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]); addedge(e[i][0],e[i][1]); addedge(e[i][1],e[i][0]); } dfs1(1,0,0); getpos(1,1); build(1,0,pos-1); } int find(int u,int v){ int f1=top[u],f2=top[v]; int tmp=0; while(f1!=f2){ if(deep[f1]<deep[f2]) { swap(f1,f2); swap(u,v); } tmp=max(tmp,query(1,p[f1],p[u])); u=fa[f1];f1=top[u];//这里直接令u=fa[f1],所以上面查询最大值的时候可以直接用p[f1] } if(u==v) return tmp; if(deep[u]>deep[v]) swap(u,v); return max(tmp,query(1,p[son[u]],p[v]));//对每个节点来说,儿子可能有多个,但父结点只有一个,所以用一条边的下方的结点表示该边 } int main() { #ifndef ONLINE_JUDGE //freopen("in.txt","r",stdin); #endif int T; scanf("%d",&T); while(T--){ init(); for(int i=0;i<n-1;i++){ if(deep[e[i][0]]>deep[e[i][1]]) swap(e[i][0],e[i][1]); update(1,p[e[i][1]],e[i][2]); } char op[10]; int a,b; while(scanf("%s",op)==1){ if(op[0]=='D') break; scanf("%d%d",&a,&b); if(op[0]=='Q'){ printf("%d\n",find(a,b)); } else update(1,p[e[a-1][1]],b);//编号从0开始 } } return 0; }
原文地址:http://blog.csdn.net/lj94093/article/details/46368235