题目大意:一棵点权树,支持点修改,子树修改,查询根路径前缀和
题解:很久以前写过,不知道为什么WA了,现在又重构了一下就过了……
我的收获:模板题
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100005
#define INF 0x3f3f3f3f
typedef long long ll;
int n,q,a[N];
int t,head[N];
int fa[N],dep[N],son[N];
int sz[N];
int tim,top[N],tree[N],pre[N];
struct edge{int to,nex;}e[N<<1];
void add(int u,int v){e[t].to=v,e[t].nex=head[u],head[u]=t++;}
struct SegmentTree{
#define ls x<<1
#define rs x<<1|1
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
#define root 1,n,1
ll add[N<<2],sum[N<<2];
inline void pushup(int x){sum[x]=sum[x<<1]+sum[x<<1|1];}
inline void pushdown(int x,int m)
{
if(!add[x]) return ;
add[ls]+=add[x],add[rs]+=add[x];
sum[ls]+=add[x]*(m-(m>>1));
sum[rs]+=add[x]*(m>>1);
add[x]=0;
}
void build(int l,int r,int x)
{
if(l==r){sum[x]=a[pre[l]];return ;}
int m=(l+r)>>1;
build(lson);build(rson);
pushup(x);
}
void updata(int L,int R,int v,int l,int r,int x)
{
if(L<=l&&r<=R){add[x]+=v;sum[x]+=(ll)v*(r-l+1);return ;}
pushdown(x,r-l+1);
int m=(l+r)>>1;
if(L<=m) updata(L,R,v,lson);
if(R>m) updata(L,R,v,rson);
pushup(x);
}
ll query(int L,int R,int l,int r,int x)
{
if(L<=l&&r<=R) return sum[x];
pushdown(x,r-l+1);
int m=(l+r)>>1;ll ans=0;
if(L<=m) ans+=query(L,R,lson);
if(R>m) ans+=query(L,R,rson);
return ans;
}
}T;
void dfs(int x)
{
sz[x]=1;
for(int i=head[x];i!=-1;i=e[i].nex){
int v=e[i].to;
if(v!=fa[x]){
fa[v]=x,dep[v]=dep[x]+1;
dfs(v);sz[x]+=sz[v];
if(!son[x]||sz[v]>sz[son[x]]) son[x]=v;
}
}
}
void dfs2(int x,int tp)
{
top[x]=tp;tree[x]=++tim;
pre[tree[x]]=x;
if(!son[x]) return;
dfs2(son[x],tp);
for(int i=head[x];i!=-1;i=e[i].nex){
int v=e[i].to;
if(v!=son[x]&&v!=fa[x]) dfs2(v,v);
}
}
ll find_sum(int x,int y)
{
int f1=top[x],f2=top[y];ll ans=0;
while(f1!=f2)
{
if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
ans+=T.query(tree[f1],tree[x],root);
x=fa[f1];f1=top[x];
}
ans+=dep[x]>dep[y]?T.query(tree[y],tree[x],root):T.query(tree[x],tree[y],root);
return ans;
}
void work()
{
int opt,x,y;
while(q--){
scanf("%d%d",&opt,&x);
if(opt==1) scanf("%d",&y),T.updata(tree[x],tree[x],y,root);
if(opt==2) scanf("%d",&y),T.updata(tree[x],tree[x]+sz[x]-1,y,root);
if(opt==3) printf("%lld\n",find_sum(x,1));
}
}
void init()
{
scanf("%d%d",&n,&q);
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int x,y,i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs(1);dfs2(1,1);
T.build(root);
}
int main()
{
init();
work();
return 0;
}