洛谷 P2590 [ZJOI2008]树的统计 题解
树链剖分板子,两次 DFS 预处理之后用线段树维护,问题转化为单点修改,区间查询(求和、最大值),对于询问路径跳到 LCA 上再查询即可。
//P2590 [ZJOI2008]树的统计 #pragma GCC optimize("Ofast") #include <bits/stdc++.h> using namespace std; const int MAXN=500005; int siz[MAXN],fa[MAXN],dep[MAXN],head[MAXN],to[MAXN],nxt[MAXN],cnt,seg[MAXN],rev[MAXN],top[MAXN],mx[MAXN],sum[MAXN],num[MAXN],son[MAXN],maxx,summ; /***********线段树***********/ void build(int k,int l,int r) { int mid=(l+r)>>1; if(l==r) { mx[k]=sum[k]=num[rev[l]]; return; } build(k<<1,l,mid); build(k<<1|1,mid+1,r); sum[k]=sum[k<<1]+sum[k<<1|1]; mx[k]=max(mx[k<<1],mx[k<<1|1]); return; } void update(int k,int l,int r,int val,int pos) { int mid; if(pos>r||pos<l) { return; } if(l==r&&r==pos) { sum[k]=val; mx[k]=val; return; } mid=(l+r)>>1; if(mid>=pos) { update(k<<1,l,mid,val,pos); } if(mid+1<=pos) { update(k<<1|1,mid+1,r,val,pos); } sum[k]=sum[k<<1]+sum[(k<<1)+1]; mx[k]=max(mx[k<<1],mx[(k<<1)+1]); return; } void query(int k,int l,int r,const int L,const int R) { int mid; if(L>r||R<l) { return; } if(L<=l&&r<=R) { summ+=sum[k]; maxx=max(maxx,mx[k]); return; } mid=(l+r)>>1; if(mid>=L) { query(k<<1,l,mid,L,R); } if(mid+1<=R) { query(k<<1|1,mid+1,r,L,R); } return; } /***********树链剖分***********/ void addedge(int x,int y) { nxt[++cnt]=head[x]; head[x]=cnt; to[cnt]=y; return; } void DFS1(int u,int f) { int v; siz[u]=1; fa[u]=f; dep[u]=dep[f]+1; for(int i=head[u];i;i=nxt[i]) { v=to[i]; if(v==f) { continue; } DFS1(v,u); siz[u]+=siz[v]; if(siz[v]>siz[son[u]]) { son[u]=v; } } return; } void DFS2(int u) { int v; if(son[u]) { seg[son[u]]=++seg[0]; top[son[u]]=top[u]; rev[seg[0]]=son[u]; DFS2(son[u]); } for(int i=head[u];i;i=nxt[i]) { v=to[i]; if(!top[v]) { seg[v]=++seg[0]; rev[seg[0]]=v; top[v]=v; DFS2(v); } } return; } /***********Main***********/ void ask(int x,int y) { int fx=top[x],fy=top[y]; while(fx!=fy) { if(dep[fx]<dep[fy]) { swap(x,y); swap(fx,fy); } query(1,1,seg[0],seg[fx],seg[x]); x=fa[fx]; fx=top[x]; } if(dep[x]>dep[y]) { swap(x,y); } query(1,1,seg[0],seg[x],seg[y]); return; } int main() { int n,x,y,m; char op[10]; scanf("%d",&n); for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } for(int i=1;i<=n;i++) { scanf("%d",&num[i]); } DFS1(1,0); seg[0]=seg[1]=top[1]=rev[1]=1; DFS2(1); build(1,1,seg[0]); scanf("%d",&m); while(m--) { scanf("%s %d %d",op,&x,&y); if(op[0]=='C') { update(1,1,seg[0],y,seg[x]); } else { summ=0; maxx=-10000000; ask(x,y); if(op[1]=='M') { printf("%d\n",maxx); } else { printf("%d\n",summ); } } } return 0; } /* * 洛谷 * https://www.luogu.com.cn/problem/P2590 * C++20 -Ofast * 2022.9.12 */
本文作者:Day_Dreamer_D
本文链接:https://www.cnblogs.com/2020gyk080/p/16686479.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
,
,
,
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步