[HAOI2015]树上操作题解
[HAOI2015]树上操作题解
一句话题意
在有权值得树上实现单点修改,和某个子树所有点修改,加上路径权值和的查询
基本上看到题就能想出怎么做的了,很明显的树剖加线段树维护,再求个lca即可,甚至一个端点都确定了。
题解
先进行两次dfs,对树进行重链剖分,这样可以使树在各个小区间上是有序的,方便用线段树维护。
然后建树,在修改时,将单点修改看作区间修改即可,唯二需要注意的是不论懒标记还是sum区间和都是在原来权值上加,即赋值时为“+=”而不是“=”,并且需要开longlong
标程
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MN=2e6+100;
int n,m,cnt;
int w[MN],head[MN];
struct node{
int nxt,to;
}e[MN<<1];
inline void add(int a,int b){
e[++cnt].nxt=head[a],head[a]=cnt,e[cnt].to=b;
}
int dep[MN],fa[MN],son[MN],siz[MN];
void dfs1(int now,int pre){
fa[now]=pre;
siz[now]=1;
dep[now]=dep[pre]+1;
for(int i=head[now];i;i=e[i].nxt){
int to=e[i].to;
if(to==pre)continue;
dfs1(to,now);
siz[now]+=siz[to];
if(siz[to]>siz[son[now]]){
son[now]=to;
}
}
}
int top[MN],dfn[MN],tot,name[MN];
void dfs2(int now,int tp){
top[now]=tp;
dfn[now]=++tot;
name[tot]=now;
if(son[now]){
dfs2(son[now],tp);
}
for(int i=head[now];i;i=e[i].nxt){
int to=e[i].to;
if(to==fa[now]||to==son[now])continue;
dfs2(to,to);
}
}
int tag[MN];
struct tree{
int l,r,sum;
}t[MN<<2];
inline void pushup(int id){
t[id].sum=t[id<<1].sum+t[id<<1|1].sum;
}
inline void pushdown(int id){
if(tag[id]==0)return;
t[id<<1].sum+=(t[id<<1].r-t[id<<1].l+1)*tag[id],tag[id<<1]+=tag[id];
t[id<<1|1].sum+=(t[id<<1|1].r-t[id<<1|1].l+1)*tag[id],tag[id<<1|1]+=tag[id];
tag[id]=0;
}
void build(int id,int l,int r){
t[id].l=l,t[id].r=r;
if(l==r){
t[id].sum=w[name[l]];
return;
}
int mid=(l+r)>>1;
build(id<<1,l,mid),build(id<<1|1,mid+1,r);
pushup(id);
}
void update(int id,int l,int r,int a){
if(t[id].l>=l&&t[id].r<=r){
tag[id]+=a;
t[id].sum+=(t[id].r-t[id].l+1)*a;
return;
}
int mid=(t[id].r+t[id].l)>>1;
pushdown(id);
if(l<=mid)update(id<<1,l,r,a);
if(r>=mid+1)update(id<<1|1,l,r,a);
pushup(id);
}
int get_sum(int id,int l,int r){
if(t[id].l>=l&&t[id].r<=r){
return t[id].sum;
}
int mid=(t[id].r+t[id].l)>>1,ans=0;
pushdown(id);
if(l<=mid)ans+=get_sum(id<<1,l,r);
if(r>=mid+1)ans+=get_sum(id<<1|1,l,r);
return ans;
}
int query(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans+=get_sum(1,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans+=get_sum(1,dfn[y],dfn[x]);
return ans;
}
signed main(){
//freopen("haoi2015.in","r",stdin);
//freopen("haoi2015.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;++i)scanf("%lld",&w[i]);
for(int i=1,a,b;i<n;++i)scanf("%lld%lld",&a,&b),add(a,b),add(b,a);
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
while(m--){
int op,x,a;
scanf("%lld%lld",&op,&x);
if(op==1){
scanf("%lld",&a);
update(1,dfn[x],dfn[x],a);
}
else if(op==2){
scanf("%lld",&a);
update(1,dfn[x],dfn[x]+siz[x]-1,a);
}
else{
printf("%lld\n",query(1,x));
}
}
return 0;
}

浙公网安备 33010602011771号