正题
题目大意
一棵带权树,要求单点修改,路径求和和路径求最大值。
解题思路
先来一个树链剖分,然后线段树维护。
codecodecode
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=31000;
int tot,cnt,n,m,ls[N],pw[N],id[N];
int siz[N],dep[N],f[N],son[N],seg[N],top[N];
struct treenode{int l,r,maxs,val;
};
struct LineTree{treenode t[N*4];void build(int x,int l,int r){t[x].l=l;t[x].r=r;if(l==r){t[x].val=t[x].maxs=pw[id[l]];return;}int mid=(l+r)>>1;build(x*2,l,mid);build(x*2+1,mid+1,r);t[x].val=t[x*2].val+t[x*2+1].val;t[x].maxs=max(t[x*2].maxs,t[x*2+1].maxs);}void Change(int x,int k,int num){if(t[x].l==t[x].r){t[x].val=t[x].maxs=num;return;}int mid=(t[x].l+t[x].r)/2;if(k<=mid) Change(x*2,k,num);else Change(x*2+1,k,num);t[x].val=t[x*2].val+t[x*2+1].val;t[x].maxs=max(t[x*2].maxs,t[x*2+1].maxs);}int Fine_sum(int x,int l,int r){if(t[x].l==l&&t[x].r==r)return t[x].val;int mid=(t[x].l+t[x].r)>>1;if(r<=mid) return Fine_sum(x*2,l,r);else if(l>mid) return Fine_sum(x*2+1,l,r);else return Fine_sum(x*2,l,mid)+Fine_sum(x*2+1,mid+1,r); }int Fine_maxs(int x,int l,int r){if(t[x].l==l&&t[x].r==r)return t[x].maxs;int mid=(t[x].l+t[x].r)>>1;if(r<=mid) return Fine_maxs(x*2,l,r);else if(l>mid) return Fine_maxs(x*2+1,l,r);else return max(Fine_maxs(x*2,l,mid),Fine_maxs(x*2+1,mid+1,r)); }
}LT;
struct edge_node{int to,next;
}a[N*2];
void addl(int x,int y)
{a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;
}
void dfs1(int x,int fa)
{siz[x]=1;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa) continue;dep[y]=dep[x]+1;f[y]=x;dfs1(y,x);siz[x]+=siz[y];if(siz[y]>siz[son[x]])son[x]=y;}
}
void dfs2(int x,int fa)
{seg[x]=++cnt;id[cnt]=x;if(son[x]){top[son[x]]=top[x];dfs2(son[x],x);}for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa||y==son[x]) continue;top[y]=y;dfs2(y,x);}
}
int path_ask_sum(int x,int y)
{int ans=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);ans+=LT.Fine_sum(1,seg[top[x]],seg[x]);x=f[top[x]];}if(dep[x]>dep[y]) swap(x,y);ans+=LT.Fine_sum(1,seg[x],seg[y]);return ans;
}
int path_ask_maxs(int x,int y)
{int ans=-2147483647;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);ans=max(ans,LT.Fine_maxs(1,seg[top[x]],seg[x]));x=f[top[x]];}if(dep[x]>dep[y]) swap(x,y);ans=max(ans,LT.Fine_maxs(1,seg[x],seg[y]));return ans;
}
int main()
{scanf("%d",&n);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}for(int i=1;i<=n;i++)scanf("%d",&pw[i]);dfs1(1,0);top[1]=1;dfs2(1,0);LT.build(1,1,n);scanf("%d",&m);for(int i=1;i<=m;i++){char c[10];int u,v;scanf("%s%d%d",c,&u,&v);if(c[1]=='H') LT.Change(1,seg[u],v);else if(c[1]=='M') printf("%d\n",path_ask_maxs(u,v));else printf("%d\n",path_ask_sum(u,v));}
}