P2590 [ZJOI2008]树的统计(树链剖分)
Posted kafuuchino
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2590 [ZJOI2008]树的统计(树链剖分)相关的知识,希望对你有一定的参考价值。
虽然是入门树剖模板
但是我终于1A了(大哭)
懒得写啥了(逃
#include<iostream> #include<cstdio> #include<cstring> using namespace std; inline int Max(int a,int b){return a>b?a:b;} inline void Swap(int &a,int &b){a^=b^=a^=b;} #define N 30005 int n,Q,Top[N],bgs[N],siz[N],fa[N],val[N]; int ID,id[N],tmp[N],sum[N<<2],mxd[N<<2]; int cnt,hd[N],nxt[N<<1],ed[N],poi[N<<1]; #define lc o<<1 #define rc o<<1|1 #define mid (l+r)/2 inline void adde(int x,int y){ nxt[ed[x]]=++cnt; hd[x]=hd[x]?hd[x]:cnt; ed[x]=cnt; poi[cnt]=y; } inline void up(int o){ sum[o]=sum[lc]+sum[rc]; mxd[o]=Max(mxd[lc],mxd[rc]); } void build(int o,int l,int r){ if(l==r){sum[o]=mxd[o]=tmp[l]; return ;} build(lc,l,mid); build(rc,mid+1,r); up(o); } void modi(int o,int l,int r,int x,int v){ if(l==r){sum[o]=mxd[o]=v; return ;} if(x<=mid) modi(lc,l,mid,x,v); else modi(rc,mid+1,r,x,v); up(o); } int ask1(int o,int l,int r,int x1,int x2){ if(x1<=l&&r<=x2) return mxd[o]; int re=-1e9; if(x1<=mid) re=Max(re,ask1(lc,l,mid,x1,x2)); if(x2>mid) re=Max(re,ask1(rc,mid+1,r,x1,x2)); return re; } int ask2(int o,int l,int r,int x1,int x2){ if(x1<=l&&r<=x2) return sum[o]; int re=0; if(x1<=mid) re+=ask2(lc,l,mid,x1,x2); if(x2>mid) re+=ask2(rc,mid+1,r,x1,x2); return re; } void dfs1(int x,int Fa){ fa[x]=Fa; siz[x]=1; for(int i=hd[x];i;i=nxt[i]){ int to=poi[i]; if(to==Fa) continue; dfs1(to,x); if(siz[to]>siz[bgs[x]]) bgs[x]=to; siz[x]+=siz[to]; } } void dfs2(int x,int tp){ tmp[id[x]=++ID]=val[x]; Top[x]=tp; if(bgs[x]) dfs2(bgs[x],tp); for(int i=hd[x];i;i=nxt[i]){ int to=poi[i]; if(to==fa[x]||to==bgs[x]) continue; dfs2(to,to); } } int Amax(int x,int y){ int re=-1e9; for(;Top[x]!=Top[y];x=fa[Top[x]]){ if(id[Top[x]]<id[Top[y]]) Swap(x,y); re=Max(re,ask1(1,1,n,id[Top[x]],id[x])); }if(id[x]>id[y]) Swap(x,y); return Max(re,ask1(1,1,n,id[x],id[y])); } int Asum(int x,int y){ int re=0; for(;Top[x]!=Top[y];x=fa[Top[x]]){ if(id[Top[x]]<id[Top[y]]) Swap(x,y); re+=ask2(1,1,n,id[Top[x]],id[x]); }if(id[x]>id[y]) Swap(x,y); return re+ask2(1,1,n,id[x],id[y]); } int main(){ scanf("%d",&n); int q1,q2; char opt[9]; for(int i=1;i<n;++i) scanf("%d%d",&q1,&q2),adde(q1,q2),adde(q2,q1); for(int i=1;i<=n;++i) scanf("%d",&val[i]); dfs1(1,0); dfs2(1,1);build(1,1,n); scanf("%d",&Q); while(Q--){ scanf("%s%d%d",opt,&q1,&q2); if(opt[1]==‘H‘) modi(1,1,n,id[q1],q2); else if(opt[1]==‘M‘) printf("%d ",Amax(q1,q2)); else if(opt[1]==‘S‘) printf("%d ",Asum(q1,q2)); }return 0; }
以上是关于P2590 [ZJOI2008]树的统计(树链剖分)的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)
bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)
1036: [ZJOI2008]树的统计Count(树链剖分)