这个题多了一个操作难度直线上升,看完题解才会写
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
按照题意:记录其DFS序,然后进栈是正,出栈为负,利用线段树进行更新
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#include <stack>
using namespace std;
typedef long long LL;
const int N = 800005;
struct Edge
{
int v,next;
} edge[N<<1];
int head[N],tot,cnt;
int val[N];
int in[N],out[N];
LL tree[N<<2],lazy[N<<2],seg[N];
int flag[N<<2];
int io[N];
void addEdge(int u,int v)
{
edge[tot].v = v,edge[tot].next = head[u],head[u] = tot++;
}
void init()
{
memset(head,-1,sizeof(head));
memset(val,0,sizeof(val));
memset(lazy,0,sizeof(lazy));
memset(io,0,sizeof(io));
memset(seg,0,sizeof(seg));
tot = cnt = 0;
}
void dfs(int u,int fa)
{
seg[in[u] = ++cnt] = (LL)val[u];
io[cnt] = 1;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
if(edge[i].v != fa)
{
dfs(edge[i].v,u);
}
}
seg[out[u] = ++cnt] = (LL)(-val[u]);
io[cnt] = -1;
}
void pushup(int idx)
{
tree[idx] = tree[idx<<1]+tree[idx<<1|1];
return;
}
void pushdown(int idx)
{
if(lazy[idx])
{
tree[idx << 1] += flag[idx<<1]*lazy[idx];
tree[idx << 1 | 1] += flag[idx<<1|1]*lazy[idx];
lazy[idx << 1] += lazy[idx];
lazy[idx << 1 | 1] += lazy[idx];
lazy[idx] = 0;
}
return;
}
void build(int l,int r,int idx)
{
if(l==r)
{
tree[idx] = seg[l];
if(io[l]>0) flag[idx] = 1;
else flag[idx] = -1;
return;
}
int mid = (l+r)>>1;
build(l,mid,idx<<1);
build(mid+1,r,idx<<1|1);
pushup(idx);
flag[idx] = flag[idx<<1] + flag[idx<<1|1];
}
void update(int l,int r,int L,int R,int idx,int val)
{
if(l>=L&&r<=R)
{
tree[idx] =tree[idx] + (LL)flag[idx]*val;
lazy[idx] =lazy[idx] + (LL)val;
return;
}
int mid = (l+r)>>1;
pushdown(idx);
if(mid>=L) update(l,mid,L,R,idx<<1,val);
if(mid<R) update(mid+1,r,L,R,idx<<1|1,val);
pushup(idx);
}
LL query(int l,int r,int L,int R,int idx){
if(l>=L&&r<=R)
{
return tree[idx];
}
int mid = (l+r)>>1;
LL sum = 0;
pushdown(idx);
if(mid>=L) sum+=query(l,mid,L,R,idx<<1);
if(mid<R) sum+=query(mid+1,r,L,R,idx<<1|1);
return sum;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=1; i<=n; i++)
{
scanf("%d",&val[i]);
}
for(int i=1; i<n; i++)
{
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,v);
addEdge(v,u);
}
dfs(1,0);
build(1,2*n,1);
while(m--)
{
int op,x,y;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&x,&y);
update(1,2*n,in[x],in[x],1,y);
update(1,2*n,out[x],out[x],1,y);
}else if(op==2){
scanf("%d%d",&x,&y);
update(1,2*n,in[x],out[x],1,y);
}else{
scanf("%d",&x);
LL sum = query(1,2*n,1,in[x],1);
printf("%lld\n",sum);
}
}
}
}
来源:https://www.cnblogs.com/liyinggang/p/5965981.html