树链剖分
P3384 【模板】轻重链剖分/树链剖分
题目描述:
如题,已知一棵包含个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:
,表示将树从 到 结点最短路径上所有节点的值都加上 。
,表示求树从 到 结点最短路径上所有节点的值之和。
,表示将以 为根节点的子树内所有节点值都加上 。
表示求以 为根节点的子树内所有节点值之和
一些概念:
- 重子节点:表示其子节点中子树最大的子结点。如果有多个子树最大的子结点,取其一。如果没有子节点,就无重子节点
- 轻子节点:表示剩余的所有子结点。
- 从这个结点到重子节点的边为 重边。
- 到其他轻子节点的边为 轻边。
- 若干条首尾衔接的重边构成 重链。
- 把落单的结点也当作重链,那么整棵树就被剖分成若干条重链。
基本思路
dfs1
处理dep[]
节点深度,fa[]
父亲节点,sz[]
子树大小,son[]
重儿子dfs2
处理id[]
节点新编号,rk[]
新编号节点对应点权,top[]
每条链因此的顶点- 对于子节点,先访问重儿子再访问轻儿子,因此重链内的
序是连续的,而一颗子树内的 序是连续的,故可以使用线段树和树状数组维护权值和 - 当我们要处理任意两点间路径时,每次选择深度较大的链往上跳,直到两点在同一条链上。
#include<bits/stdc++.h>
#define il inline
#define ri register
#define cs const
#define pc(i) putchar(i)
using namespace std;
cs int N=2e5+7;
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) x=-x,pc('-');if(x>9) wt(x/10);pc(x%10|48);}
struct node{int to,nxt;}e[N];
int t[N<<2],lz[N<<2];
int n,m,r,Mod,h[N],v[N],eoe;
int dep[N],son[N],id[N],fa[N],sz[N],top[N],rk[N],dfn;
il void add(cs int u,cs int v){e[++eoe]={v,h[u]},h[u]=eoe;}
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)
#define len (r-l+1)
il void pushup(cs int rt){t[rt]=(t[ls]+t[rs])%Mod;}
il void pushdown(cs int rt,cs int l,cs int r)
{
if(!lz[rt]) return;
lz[ls]+=lz[rt],(t[ls]+=lz[rt]*(mid-l+1))%=Mod;
lz[rs]+=lz[rt],(t[rs]+=lz[rt]*(r-mid))%=Mod,lz[rt]=0;
}
void build(cs int rt,cs int l,cs int r)
{
if(l==r) return (t[rt]=v[rk[l]])%=Mod,void();
build(ls,l,mid),build(rs,mid+1,r),pushup(rt);
}
void update(cs int rt,cs int l,cs int r,cs int ql,cs int qr,cs int k)
{
if(ql<=l&&r<=qr) return (t[rt]+=len*k)%=Mod,lz[rt]+=k,void();
pushdown(rt,l,r);
if(ql<=mid) update(ls,l,mid,ql,qr,k);
if(qr>mid) update(rs,mid+1,r,ql,qr,k);
pushup(rt);
}
int query(cs int rt,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr) return t[rt]%Mod;
int re=0; pushdown(rt,l,r);
if(ql<=mid) (re+=query(ls,l,mid,ql,qr))%=Mod;
if(qr>mid) (re+=query(rs,mid+1,r,ql,qr))%=Mod;
return re;
}
#undef ls
#undef rs
#undef mid
#undef len
void dfs1(cs int u,cs int Fa)//dep,fa,sz,hson
{
dep[u]=dep[Fa]+1,fa[u]=Fa,sz[u]=1;int hs=-1;
for(ri int i=h[u];i;i=e[i].nxt)
{
if(e[i].to==Fa) continue;
dfs1(e[i].to,u),sz[u]+=sz[e[i].to];
if(sz[e[i].to]>hs) son[u]=e[i].to,hs=sz[e[i].to];
}
}
void dfs2(cs int u,cs int tp)//id,rk,top
{
id[u]=++dfn,rk[dfn]=u,top[u]=tp;
if(!son[u]) return;
dfs2(son[u],tp);
for(ri int i=h[u];i;i=e[i].nxt)
if(e[i].to!=fa[u]&&e[i].to!=son[u])
dfs2(e[i].to,e[i].to);
}
il int qRange(int a,int b)
{
int re=0;
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
(re+=query(1,1,n,id[top[a]],id[a]))%=Mod,a=fa[top[a]];
}
if(dep[a]>dep[b]) swap(a,b);
return (re+=query(1,1,n,id[a],id[b]))%=Mod,re;
}
il void updRange(int a,int b,cs int k)
{
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
update(1,1,n,id[top[a]],id[a],k),a=fa[top[a]];
}
if(dep[a]>dep[b]) swap(a,b);
update(1,1,n,id[a],id[b],k);
}
il int qSon(cs int u){return query(1,1,n,id[u],id[u]+sz[u]-1);}
il void updSon(cs int u,cs int k){update(1,1,n,id[u],id[u]+sz[u]-1,k);}
signed main()
{
read(n),read(m),read(r),read(Mod);
for(ri int i=1;i<=n;++i) read(v[i]);
for(ri int i=1,u,v;i<n;++i)
read(u),read(v),add(u,v),add(v,u);
dfs1(r,0),dfs2(r,r),build(1,1,n);
for(ri int i=1,op,x,y,z;i<=m;++i)
{
read(op);
if(op==1) read(x),read(y),read(z),updRange(x,y,z);
else if(op==2) read(x),read(y),wt(qRange(x,y)),pc('\n');
else if(op==3) read(x),read(z),updSon(x,z);
else read(x),wt(qSon(x)),pc('\n');
}
return 0;
}
树剖求
感觉比板子简单捏(
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
using namespace std;
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) x=-x,pc('-');if(x>9) wt(x/10);pc(x%10|48);}
cs int N=5e5+7;
struct node{int nxt,to;}e[N<<1];
int n,m,r,sz[N],top[N],id[N],rk[N],dep[N],son[N],fa[N],h[N],eoe,dfn;
il void add(cs int u,cs int v){e[++eoe]={h[u],v},h[u]=eoe;}
void dfs1(cs int u,cs int Fa)
{
dep[u]=dep[Fa]+1,sz[u]=1,fa[u]=Fa;int hs=-1;
for(ri int i=h[u];i;i=e[i].nxt)
{
if(e[i].to==Fa) continue;
dfs1(e[i].to,u),sz[u]+=sz[e[i].to];
if(hs<sz[e[i].to]) son[u]=e[i].to,hs=sz[e[i].to];
}
}
void dfs2(cs int u,cs int tp)
{
top[u]=tp,id[u]=++dfn,rk[dfn]=u;
if(!son[u]) return;
dfs2(son[u],tp);
for(ri int i=h[u];i;i=e[i].nxt)
if(e[i].to!=son[u]&&e[i].to!=fa[u])
dfs2(e[i].to,e[i].to);
}
il int lca(int a,int b)
{
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
a=fa[top[a]];
}
return dep[a]<dep[b]?a:b;
}
signed main()
{
read(n),read(m),read(r);
for(ri int i=1,u,v;i<n;++i)
read(u),read(v),add(u,v),add(v,u);
dfs1(r,0),dfs2(r,r);
for(ri int i=1,a,b;i<=m;++i)
read(a),read(b),wt(lca(a,b)),pc('\n');
return 0;
}
P2590 [ZJOI2008]树的统计
单点修改,加了一个路径最大值,改下线段树就行,记得传进线段树的编号要套上一个id[]
……
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
using namespace std;
cs int N=5e5+7,inf=1e9+7;
struct node{int nxt,to;}e[N<<1];
int t[N<<2][2],h[N],eoe,v[N];
int n,q,sz[N],top[N],id[N],rk[N],dep[N],son[N],fa[N],dfn;
il void add(cs int u,cs int v){e[++eoe]={h[u],v},h[u]=eoe;}
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (rt<<1|1)
#define len (r-l+1)
il void pushup(cs int rt)
{
t[rt][0]=t[ls][0]+t[rs][0],
t[rt][1]=max(t[ls][1],t[rs][1]);
}
void build(cs int rt,cs int l,cs int r)
{
if(l==r) return t[rt][0]=t[rt][1]=v[rk[l]],void();
build(ls,l,mid),build(rs,mid+1,r),pushup(rt);
}
void update(cs int rt,cs int l,cs int r,cs int q,cs int k)
{
if(l==r) return t[rt][0]=t[rt][1]=k,void();
if(q<=mid) update(ls,l,mid,q,k);
else update(rs,mid+1,r,q,k);
pushup(rt);
}
int querySum(cs int rt,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr) return t[rt][0];
int re=0;
if(ql<=mid) re+=querySum(ls,l,mid,ql,qr);
if(qr>mid) re+=querySum(rs,mid+1,r,ql,qr);
return re;
}
int queryMax(cs int rt,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr) return t[rt][1];
int re=-inf;
if(ql<=mid) re=max(re,queryMax(ls,l,mid,ql,qr));
if(qr>mid) re=max(re,queryMax(rs,mid+1,r,ql,qr));
return re;
}
#undef mid
#undef ls
#undef rs
#undef len
void dfs1(cs int u,cs int Fa)
{
dep[u]=dep[Fa]+1,sz[u]=1,fa[u]=Fa;int hs=-1;
for(ri int i=h[u];i;i=e[i].nxt)
{
if(e[i].to==Fa) continue;
dfs1(e[i].to,u),sz[u]+=sz[e[i].to];
if(hs<sz[e[i].to]) son[u]=e[i].to,hs=sz[e[i].to];
}
}
void dfs2(cs int u,cs int tp)
{
top[u]=tp,id[u]=++dfn,rk[dfn]=u;
if(!son[u]) return;
dfs2(son[u],tp);
for(ri int i=h[u];i;i=e[i].nxt)
if(e[i].to!=son[u]&&e[i].to!=fa[u])
dfs2(e[i].to,e[i].to);
}
il int qRange(int a,int b)
{
int re=0;
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
re+=querySum(1,1,n,id[top[a]],id[a]),a=fa[top[a]];
}
if(dep[a]>dep[b]) swap(a,b);
return re+=querySum(1,1,n,id[a],id[b]),re;
}
il int qMax(int a,int b)
{
int re=-inf;
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
re=max(re,queryMax(1,1,n,id[top[a]],id[a])),a=fa[top[a]];
}
if(dep[a]>dep[b]) swap(a,b);
return max(re,queryMax(1,1,n,id[a],id[b]));
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n;
for(ri int i=1,u,v;i<n;++i)
cin>>u>>v,add(u,v),add(v,u);
for(ri int i=1;i<=n;++i) cin>>v[i];
dfs1(1,0),dfs2(1,1),build(1,1,n);
cin>>q;
for(ri int i=1,u,v,t;i<=q;++i)
{
char op[10]; cin>>op;
if(op[0]=='C') cin>>u>>t,update(1,1,n,id[u],t);//id[u]
else if(op[1]=='M') cin>>u>>v,cout<<qMax(u,v)<<'\n';
else cin>>u>>v,cout<<qRange(u,v)<<'\n';
}
return 0;
}
[HAOI2015]树上操作
甚至比模板简单(开long long
点击查看代码
#include<bits/stdc++.h>
#define il inline
#define ri register
#define cs const
#define pc(i) putchar(i)
#define int long long
using namespace std;
cs int N=2e5+7;
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) x=-x,pc('-');if(x>9) wt(x/10);pc(x%10|48);}
struct node{int to,nxt;}e[N];
int t[N<<2],lz[N<<2];
int n,m,r,h[N],v[N],eoe;
int dep[N],son[N],id[N],fa[N],sz[N],top[N],rk[N],dfn;
il void add(cs int u,cs int v){e[++eoe]={v,h[u]},h[u]=eoe;}
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)
#define len (r-l+1)
il void pushup(cs int rt){t[rt]=t[ls]+t[rs];}
il void pushdown(cs int rt,cs int l,cs int r)
{
if(!lz[rt]) return;
lz[ls]+=lz[rt],t[ls]+=lz[rt]*(mid-l+1);
lz[rs]+=lz[rt],t[rs]+=lz[rt]*(r-mid),lz[rt]=0;
}
void build(cs int rt,cs int l,cs int r)
{
if(l==r) return t[rt]=v[rk[l]],void();
build(ls,l,mid),build(rs,mid+1,r),pushup(rt);
}
void update(cs int rt,cs int l,cs int r,cs int ql,cs int qr,cs int k)
{
if(ql<=l&&r<=qr) return t[rt]+=len*k,lz[rt]+=k,void();
pushdown(rt,l,r);
if(ql<=mid) update(ls,l,mid,ql,qr,k);
if(qr>mid) update(rs,mid+1,r,ql,qr,k);
pushup(rt);
}
int query(cs int rt,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr) return t[rt];
int re=0; pushdown(rt,l,r);
if(ql<=mid) re+=query(ls,l,mid,ql,qr);
if(qr>mid) re+=query(rs,mid+1,r,ql,qr);
return re;
}
#undef ls
#undef rs
#undef mid
#undef len
void dfs1(cs int u,cs int Fa)//dep,fa,sz,hson
{
dep[u]=dep[Fa]+1,fa[u]=Fa,sz[u]=1;int hs=-1;
for(ri int i=h[u];i;i=e[i].nxt)
{
if(e[i].to==Fa) continue;
dfs1(e[i].to,u),sz[u]+=sz[e[i].to];
if(sz[e[i].to]>hs) son[u]=e[i].to,hs=sz[e[i].to];
}
}
void dfs2(cs int u,cs int tp)//id,rk,top
{
id[u]=++dfn,rk[dfn]=u,top[u]=tp;
if(!son[u]) return;
dfs2(son[u],tp);
for(ri int i=h[u];i;i=e[i].nxt)
if(e[i].to!=fa[u]&&e[i].to!=son[u])
dfs2(e[i].to,e[i].to);
}
il int qRange(int a,int b)
{
int re=0;
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
re+=query(1,1,n,id[top[a]],id[a]),a=fa[top[a]];
}
if(dep[a]>dep[b]) swap(a,b);
return re+=query(1,1,n,id[a],id[b]),re;
}
il void updRange(int a,int b,cs int k)
{
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
update(1,1,n,id[top[a]],id[a],k),a=fa[top[a]];
}
if(dep[a]>dep[b]) swap(a,b);
update(1,1,n,id[a],id[b],k);
}
il void updSon(cs int u,cs int k){update(1,1,n,id[u],id[u]+sz[u]-1,k);}
signed main()
{
// freopen("1.in","r",stdin);
read(n),read(m);
for(ri int i=1;i<=n;++i) read(v[i]);
for(ri int i=1,u,v;i<n;++i)
read(u),read(v),add(u,v),add(v,u);
dfs1(1,0),dfs2(1,1),build(1,1,n);
for(ri int i=1,op,x,y,z;i<=m;++i)
{
read(op);
if(op==1) read(x),read(z),updRange(x,x,z);
else if(op==2) read(x),read(z),updSon(x,z);
else read(x),wt(qRange(1,x)),pc('\n');
}
return 0;
}
P3833 [SHOI2012]魔法树
甚至比模板简单
点击查看代码
#include<bits/stdc++.h>
#define il inline
#define ri register
#define cs const
#define pc(i) putchar(i)
#define int long long
using namespace std;
cs int N=2e5+7;
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
il void Ro(char &ch){ch=' ';while(ch!='A'&&ch!='Q')ch=getchar();}
void wt(int x){if(x<0) x=-x,pc('-');if(x>9) wt(x/10);pc(x%10|48);}
struct node{int to,nxt;}e[N];
int t[N<<2],lz[N<<2];
int n,m,r,h[N],v[N],eoe;
int dep[N],son[N],id[N],fa[N],sz[N],top[N],rk[N],dfn;
il void add(cs int u,cs int v){e[++eoe]={v,h[u]},h[u]=eoe;}
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)
#define len (r-l+1)
il void pushup(cs int rt){t[rt]=t[ls]+t[rs];}
il void pushdown(cs int rt,cs int l,cs int r)
{
if(!lz[rt]) return;
lz[ls]+=lz[rt],t[ls]+=lz[rt]*(mid-l+1);
lz[rs]+=lz[rt],t[rs]+=lz[rt]*(r-mid),lz[rt]=0;
}
void build(cs int rt,cs int l,cs int r)
{
if(l==r) return t[rt]=v[rk[l]],void();
build(ls,l,mid),build(rs,mid+1,r),pushup(rt);
}
void update(cs int rt,cs int l,cs int r,cs int ql,cs int qr,cs int k)
{
if(ql<=l&&r<=qr) return t[rt]+=len*k,lz[rt]+=k,void();
pushdown(rt,l,r);
if(ql<=mid) update(ls,l,mid,ql,qr,k);
if(qr>mid) update(rs,mid+1,r,ql,qr,k);
pushup(rt);
}
int query(cs int rt,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr) return t[rt];
int re=0; pushdown(rt,l,r);
if(ql<=mid) re+=query(ls,l,mid,ql,qr);
if(qr>mid) re+=query(rs,mid+1,r,ql,qr);
return re;
}
#undef ls
#undef rs
#undef mid
#undef len
void dfs1(cs int u,cs int Fa)//dep,fa,sz,hson
{
dep[u]=dep[Fa]+1,fa[u]=Fa,sz[u]=1;int hs=-1;
for(ri int i=h[u];i;i=e[i].nxt)
{
if(e[i].to==Fa) continue;
dfs1(e[i].to,u),sz[u]+=sz[e[i].to];
if(sz[e[i].to]>hs) son[u]=e[i].to,hs=sz[e[i].to];
}
}
void dfs2(cs int u,cs int tp)//id,rk,top
{
id[u]=++dfn,rk[dfn]=u,top[u]=tp;
if(!son[u]) return;
dfs2(son[u],tp);
for(ri int i=h[u];i;i=e[i].nxt)
if(e[i].to!=fa[u]&&e[i].to!=son[u])
dfs2(e[i].to,e[i].to);
}
il void updRange(int a,int b,cs int k)
{
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
update(1,1,n,id[top[a]],id[a],k),a=fa[top[a]];
}
if(dep[a]>dep[b]) swap(a,b);
update(1,1,n,id[a],id[b],k);
}
il int qSon(cs int u){return query(1,1,n,id[u],id[u]+sz[u]-1);}
signed main()
{
// freopen("1.in","r",stdin);
read(n);
for(ri int i=1,u,v;i<n;++i)
read(u),read(v),add(u,v),add(v,u);
dfs1(0,0),dfs2(0,0),build(1,1,n);
read(m);
for(ri int i=1,x,y,z;i<=m;++i)
{
char op; Ro(op);
if(op=='A') read(x),read(y),read(z),updRange(x,y,z);
else read(x),wt(qSon(x)),pc('\n');
}
return 0;
}
P1505 [国家集训队]旅游
线段树维护区间
调了一天很崩溃捏
#include<bits/stdc++.h>
#define il inline
#define ri register
#define cs const
#define pc(i) putchar(i)
using namespace std;
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) x=-x,pc('-');if(x>9) wt(x/10);pc(x%10|48);}
cs int N=2e5+7,inf=INT_MAX;
struct Seg{int lz,sum,Max,Min;}t[N<<2];
struct node{int nxt,to,w;}e[N<<1];
int n,h[N],eoe,r[N][2],m;
int val[N],son[N],top[N],id[N],fa[N],rk[N],dep[N],sz[N],dfn;
il void add(cs int u,cs int v,cs int w){e[++eoe]={h[u],v,w},h[u]=eoe;}
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)
#define len (r-l+1)
il void pushup(cs int rt)
{
t[rt].Max=max(t[ls].Max,t[rs].Max),
t[rt].Min=min(t[ls].Min,t[rs].Min),
t[rt].sum=t[ls].sum+t[rs].sum;
}
il void pushdown(cs int rt)
{
if(!t[rt].lz) return;
t[ls].lz^=1,t[rs].lz^=1,t[rt].lz=0;//调了一天能不能趋势
int maxx=t[ls].Max,minn=t[ls].Min;
t[ls]={t[ls].lz,-t[ls].sum,-minn,-maxx};
maxx=t[rs].Max,minn=t[rs].Min;
t[rs]={t[rs].lz,-t[rs].sum,-minn,-maxx};
}
void build(cs int rt,cs int l,cs int r)
{
if(l==r) return t[rt]={0,val[rk[l]],val[rk[l]],val[rk[l]]},void();
build(ls,l,mid),build(rs,mid+1,r),pushup(rt);
}
void change(cs int rt,cs int l,cs int r,cs int q,cs int k)
{
if(l==r) return t[rt]={0,k,k,k},void();
pushdown(rt);
if(q<=mid) change(ls,l,mid,q,k);
if(q>mid) change(rs,mid+1,r,q,k);
pushup(rt);
}
void update(cs int rt,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr)
{
int maxx=t[rt].Max,minn=t[rt].Min;
t[rt]={t[rt].lz^1,-t[rt].sum,-minn,-maxx};return;
}
pushdown(rt);
if(ql<=mid) update(ls,l,mid,ql,qr);
if(qr>mid) update(rs,mid+1,r,ql,qr);
pushup(rt);
}
int query_min(cs int rt,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr) return t[rt].Min;
int re=inf;pushdown(rt);
if(ql<=mid) re=min(re,query_min(ls,l,mid,ql,qr));
if(qr>mid) re=min(re,query_min(rs,mid+1,r,ql,qr));
return pushup(rt),re;
}
int query_max(cs int rt,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr) return t[rt].Max;
int re=-inf; pushdown(rt);
if(ql<=mid) re=max(re,query_max(ls,l,mid,ql,qr));
if(qr>mid) re=max(re,query_max(rs,mid+1,r,ql,qr));
return pushup(rt),re;
}
int query_sum(cs int rt,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr) return t[rt].sum;
int re=0;pushdown(rt);
if(ql<=mid) re+=query_sum(ls,l,mid,ql,qr);
if(qr>mid) re+=query_sum(rs,mid+1,r,ql,qr);
return pushup(rt),re;
}
#undef ls
#undef rs
#undef mid
#undef len
void dfs1(cs int u,cs int Fa)
{
dep[u]=dep[Fa]+1,sz[u]=1,fa[u]=Fa;int maxx=-1;
for(ri int i=h[u];i;i=e[i].nxt)
{
if(e[i].to==Fa) continue;
dfs1(e[i].to,u),sz[u]+=sz[e[i].to],val[e[i].to]=e[i].w;
if(sz[e[i].to]>maxx) maxx=sz[e[i].to],son[u]=e[i].to;
}
}
void dfs2(cs int u,cs int tp)
{
top[u]=tp,id[u]=++dfn,rk[dfn]=u;
if(!son[u]) return; dfs2(son[u],tp);
for(ri int i=h[u];i;i=e[i].nxt)
if(e[i].to!=fa[u]&&e[i].to!=son[u])
dfs2(e[i].to,e[i].to);
}
il void Chg()
{
int x,k,a,b; read(x),read(k);
a=r[x][0]+1,b=r[x][1]+1;
if(dep[a]<dep[b]) swap(a,b);
change(1,1,n,id[a],k);
}
il void Upd()
{
int a,b; read(a),read(b),a++,b++;
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
update(1,1,n,id[top[a]],id[a]),a=fa[top[a]];
}
if(a==b) return;
if(dep[a]>dep[b]) swap(a,b);
update(1,1,n,id[a]+1,id[b]);
}
il void QSum()
{
int a,b,re=0;read(a),read(b),a++,b++;
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
re+=query_sum(1,1,n,id[top[a]],id[a]),a=fa[top[a]];
}
if(a==b) return wt(re),pc('\n'),void();
if(dep[a]>dep[b]) swap(a,b);
re+=query_sum(1,1,n,id[a]+1,id[b]),wt(re),pc('\n');
}
il void QMax()
{
int a,b,re=-inf; read(a),read(b),a++,b++;
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
re=max(re,query_max(1,1,n,id[top[a]],id[a])),a=fa[top[a]];
}
if(a==b) return wt(re),pc('\n'),void();
if(dep[a]>dep[b]) swap(a,b);
re=max(re,query_max(1,1,n,id[a]+1,id[b])),wt(re),pc('\n');
}
il void QMin()
{
int a,b,re=inf; read(a),read(b),a++,b++;
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
re=min(re,query_min(1,1,n,id[top[a]],id[a])),a=fa[top[a]];
}
if(a==b) return wt(re),pc('\n'),void();
if(dep[a]>dep[b]) swap(a,b);
re=min(re,query_min(1,1,n,id[a]+1,id[b])),wt(re),pc('\n');
}
signed main()
{
read(n);
for(ri int i=1,w;i<n;++i)
read(r[i][0]),read(r[i][1]),read(w),
add(r[i][0]+1,r[i][1]+1,w),add(r[i][1]+1,r[i][0]+1,w);
read(m),dfs1(1,0),dfs2(1,1),build(1,1,n);
for(ri int i=1;i<=m;++i)
{
char op[5]; scanf("%s",op);
if(op[0]=='C') Chg();
else if(op[0]=='N') Upd();
else if(op[0]=='S') QSum();
else if(op[1]=='A') QMax();
else QMin();
}
return 0;
}
及后续内容
参考资料:https://oiwiki.org/graph/hld/
https://www.luogu.com.cn/blog/zengqinyi/solution-p3384
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】