欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1036
题意概括
一个树,每个节点有一个权值。3种操作。
1:修改某一个节点的权值。
2:询问某两个节点间的权值和
3:询问某两个节点之间的最大权值。
题解
树链剖分裸题
代码
#include <cstring> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> using namespace std; const int N=30005,Inf=33333; struct Edge{ int cnt,y[N*2],nxt[N*2],fst[N]; void clear(){ cnt=0; memset(fst,0,sizeof fst); } void add(int a,int b){ y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt; } }g; int n,m,v[N],fa[N],size[N],son[N],depth[N],top[N],p[N],ap[N],cnp; struct Tree{ int m,s; }t[N*4]; void Get_Gen_Info(int rt,int pre,int d){ depth[rt]=d,size[rt]=1,fa[rt]=pre,son[rt]=-1; for (int i=g.fst[rt];i;i=g.nxt[i]) if (g.y[i]!=pre){ int s=g.y[i]; Get_Gen_Info(s,rt,d+1); size[rt]+=size[s]; if (son[rt]==-1||size[s]>size[son[rt]]) son[rt]=s; } } void Get_Pos(int rt,int tp){ top[rt]=tp,p[rt]=++cnp,ap[cnp]=rt; if (son[rt]==-1) return; else Get_Pos(son[rt],tp); for (int i=g.fst[rt];i;i=g.nxt[i]){ int s=g.y[i]; if (s!=fa[rt]&&s!=son[rt]) Get_Pos(s,s); } } void pushup(int rt){ int ls=rt<<1,rs=ls|1; t[rt].m=max(t[ls].m,t[rs].m); t[rt].s=t[ls].s+t[rs].s; } void build(int rt,int le,int ri){ if (le==ri){ t[rt].m=t[rt].s=v[ap[le]]; return; } int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1; build(ls,le,mid); build(rs,mid+1,ri); pushup(rt); } void change(int rt,int le,int ri,int pos,int v){ if (le==ri){ t[rt].m=t[rt].s=v; return; } int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1; if (pos<=mid) change(ls,le,mid,pos,v); else change(rs,mid+1,ri,pos,v); pushup(rt); } int query(int rt,int le,int ri,int xle,int xri,int ty){ if (le>xri||ri<xle) return ty?0:-Inf; if (xle<=le&&ri<=xri) return ty?t[rt].s:t[rt].m; int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1; if (ty) return query(ls,le,mid,xle,xri,ty)+query(rs,mid+1,ri,xle,xri,ty); else return max(query(ls,le,mid,xle,xri,ty),query(rs,mid+1,ri,xle,xri,ty)); } int find(int a,int b,int t){ int f1=top[a],f2=top[b],ans=t?0:-Inf; while (f1!=f2){ if (depth[f1]<depth[f2]) swap(f1,f2),swap(a,b); if (t) ans+=query(1,1,n,p[f1],p[a],t); else ans=max(ans,query(1,1,n,p[f1],p[a],t)); a=fa[f1],f1=top[a]; } if (depth[a]>depth[b]) swap(a,b); if (t) ans+=query(1,1,n,p[a],p[b],t); else ans=max(ans,query(1,1,n,p[a],p[b],t)); return ans; } int main(){ scanf("%d",&n); g.clear(); for (int i=1,a,b;i<n;i++){ scanf("%d%d",&a,&b); g.add(a,b); g.add(b,a); } for (int i=1;i<=n;i++) scanf("%d",&v[i]); cnp=0; Get_Gen_Info(1,0,0); Get_Pos(1,1); build(1,1,n); scanf("%d",&m); for (int i=1;i<=m;i++){ char str[10]; int a,b,t; scanf("%s%d%d",str,&a,&b); if (str[0]=='C') change(1,1,n,p[a],b); else { t=str[1]=='M'?0:1; printf("%d ",find(a,b,t)); } } return 0; }