题目大意:一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
n<=3W
裸的树链剖分。。。
这题没有区间修改所以我们可以大胆地套用ZKW线段树了(太久没写都忘光了的说)
注意修改点的时候要修改的是点的重标号而不是点本身 因为这事郁闷了一会
|点权|<=3W 3W*3W=9E 所以没必要开long long int完全能解决
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 30100 using namespace std; struct abcd{ int to,next; }table[M<<1]; int head[M],tot; void add(int x,int y) { table[++tot].to=y; table[tot].next=head[x]; head[x]=tot; } int n,m,q,Max[70000],Sum[70000],fa[M],son[M],dpt[M],top[M],pos[M],siz[M],f[M],cnt; char s[100]; void dfs1(int x) { int i; dpt[x]=dpt[fa[x]]+1; siz[x]=1; for(i=head[x];i;i=table[i].next) { if(table[i].to==fa[x]) continue; fa[table[i].to]=x; dfs1(table[i].to); if(siz[table[i].to]>siz[son[x]]) son[x]=table[i].to; siz[x]+=siz[table[i].to]; } } void dfs2(int x) { int i; if(son[fa[x]]==x) top[x]=top[fa[x]]; else { top[x]=x; for(i=x;i;i=son[i]) pos[i]=++cnt; } Max[pos[x]+q]=Sum[pos[x]+q]=f[x]; for(i=head[x];i;i=table[i].next) { if(table[i].to==fa[x]) continue; dfs2(table[i].to); } } void Build_tree() { for(int i=q-1;i;i--) Max[i]=max(Max[i<<1],Max[i<<1|1]), Sum[i]=Sum[i<<1]+Sum[i<<1|1]; } void change(int x,int y) { for(x+=q,Max[x]=Sum[x]=y,x>>=1;x;x>>=1) Max[x]=max(Max[x<<1],Max[x<<1|1]), Sum[x]=Sum[x<<1]+Sum[x<<1|1]; } int getmax(int x,int y) { int re=0x80000000; for(x+=q-1,y+=q+1;x^y^1;x>>=1,y>>=1) { if(~x&1)re=max(re,Max[x^1]); if( y&1)re=max(re,Max[y^1]); } return re; } int Qmax(int x,int y) { int re=0x80000000,fx=top[x],fy=top[y]; while(fx!=fy) { if(dpt[fx]<dpt[fy]) swap(x,y),swap(fx,fy); re=max( re , getmax(pos[fx],pos[x]) ); x=fa[fx];fx=top[x]; } if(dpt[x]<dpt[y]) swap(x,y); re=max( re , getmax(pos[y],pos[x]) ); return re; } int getsum(int x,int y) { int re=0; for(x+=q-1,y+=q+1;x^y^1;x>>=1,y>>=1) { if(~x&1)re+=Sum[x^1]; if( y&1)re+=Sum[y^1]; } return re; } int Qsum(int x,int y) { int re=0,fx=top[x],fy=top[y]; while(fx!=fy) { if(dpt[fx]<dpt[fy]) swap(x,y),swap(fx,fy); re+=getsum(pos[fx],pos[x]); x=fa[fx];fx=top[x]; } if(dpt[x]<dpt[y]) swap(x,y); re+=getsum(pos[y],pos[x]); return re; } int main() { int i,x,y; cin>>n; for(q=1;q<=n+1;q<<=1); for(i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x); for(i=1;i<=n;i++) scanf("%d",&f[i]); memset(Max,0xef,sizeof Max); dfs1(1); dfs2(1); Build_tree(); cin>>m; for(i=1;i<=m;i++) { scanf("%s%d%d",s,&x,&y); if(s[1]=='M') printf("%d\n", Qmax(x,y) ); else if(s[1]=='S') printf("%d\n", Qsum(x,y) ); else change(pos[x],y); } return 0; }