洛谷P2590 树的统计(https://www.luogu.org/problem/P2590)
啊调了6个小时,血的教训啊。。。在树链剖分后,由于树按照DFN序重新编号,如果要直接调用线段树操作,需要操作ID[X]而不能直接操作编号X
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int maxn=30030; int head[maxn],top[maxn],dep[maxn],fa[maxn],id[maxn],sz[maxn],son[maxn]; int n,m,cnt,num,flag ,p,q,t; int a[maxn],b[maxn]; string k; struct pp { int u; int nex; }e[maxn*2]; struct kk { int l,r; int sum,maxl; }s[maxn*4]; void add(int x,int y) { e[++cnt].u=y; e[cnt].nex=head[x]; head[x]=cnt; } void up(int rt) { s[rt].sum=s[rt<<1].sum+s[rt<<1|1].sum; s[rt].maxl=max(s[rt<<1].maxl,s[rt<<1|1].maxl); } void build(int rt,int l,int r) { s[rt].l=l; s[rt].r=r; s[rt].maxl=-maxn*4; s[rt].sum=0; if(l==r) { s[rt].sum=s[rt].maxl=a[l]; return; } int mid=(l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } int qsum(int rt,int l,int r) { if(l<=s[rt].l&&r>=s[rt].r) return s[rt].sum; int ans=0; int mid=(s[rt].l+s[rt].r)>>1; if(l<=mid) ans+=qsum(rt<<1,l,r); if(r>mid) ans+=qsum(rt<<1|1,l,r); return ans; } int qmax(int rt,int l,int r) { if(l<=s[rt].l&&r>=s[rt].r) return s[rt].maxl; int ans=-maxn*100; int mid=(s[rt].l+s[rt].r)>>1; if(l<=mid) ans=max(ans,qmax(rt<<1,l,r)); if(r>mid) ans=max(ans,qmax(rt<<1|1,l,r)); return ans; } void modify(int rt,int x,int v) { if(s[rt].l==s[rt].r&&s[rt].r==x) { s[rt].sum=s[rt].maxl=v; return; } int mid=(s[rt].l+s[rt].r)>>1; if(x<=mid) modify(rt<<1,x,v); else modify(rt<<1|1,x,v); up(rt); } void dfs1(int x,int f,int deep) { fa[x]=f; dep[x]=deep; sz[x]=1; int ms=-1; for(int i=head[x];i;i=e[i].nex) { int y=e[i].u; if(y==f) continue; dfs1(y,x,deep+1); sz[x]+=sz[y]; if(sz[y]>ms) { ms=sz[y]; son[x]=y; } } } void dfs2(int x,int tt) { id[x]=++num; a[num]=b[x]; top[x]=tt; if(!son[x]) return; dfs2(son[x],tt); for(int i=head[x];i;i=e[i].nex) { int y=e[i].u; if(y==fa[x]||y==son[x]) continue; dfs2(y,y); } } int anssum(int x,int y) { int ans=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); ans+=qsum(1,id[top[x]],id[x]); x=fa[top[x]]; } if(dep[x]<dep[y]) swap(x,y); ans+=qsum(1,id[y],id[x]); return ans; } int ansmax(int x,int y) { int ans=-maxn*100; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap (x,y); ans=max(ans,qmax(1,id[top[x]],id[x])); x=fa[top[x]]; } if(dep[x]<dep[y]) swap(x,y); ans=max(ans,qmax(1,id[y],id[x])); return ans; } int main() { scanf("%d",&n); for(int i=1;i<=(n-1);i++) { int aa,bb; scanf("%d%d",&aa,&bb); add(aa,bb);add(bb,aa); } for(int i=1;i<=n;i++) scanf("%d",&b[i]); dfs1(1,0,1); dfs2(1,1); build(1,1,n); scanf("%d",&t); while(t--) { cin>>k; scanf("%d%d",&p,&q); if(k=="CHANGE") modify(1,id[p],q); else if(k=="QMAX") printf("%d\n",ansmax(p,q)); else printf("%d\n",anssum(p,q)); } return 0; }