# bzoj 4034(DFS序+线段树)

有一棵点数为 N 的树，以点 1 为根，且树点有边权。然后有 M 个

#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 val[N];
int in[N],out[N];
LL tree[N<<2],lazy[N<<2],seg[N];
int flag[N<<2];
int io[N];
{
}
void init()
{
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;
{
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);
}
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);
}
}
}
}

posted @ 2016-10-16 09:46  樱花庄的龙之介大人  阅读(849)  评论(0编辑  收藏  举报