bzoj4034: [HAOI2015]T2
dfs序+线段树.
首先生成树的出栈入栈序。
然后入栈设为a[u],出栈设为-a[u]。
子树在线段树上是一个连续的范围,所以三个操作都可以在线段树上实现了。
ps:val设成int,wa了无数发。。
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long LL; const int maxn = 800000 + 10; const int maxm = 800000 + 10; const int maxk = 800000 + 10; int g[maxn],v[maxm],next[maxm],eid; int n,m,vid; int a[maxm],b[maxm]; int in[maxn],out[maxn]; bool down[maxn]; //int id[maxn]; void addedge(int a,int b) { v[eid]=b; next[eid]=g[a]; g[a]=eid++; v[eid]=a; next[eid]=g[b]; g[b]=eid++; } struct Segtree { #define lc(x) ((x)<<1) #define rc(x) (((x)<<1)|1) int l[maxk],r[maxk]; LL sumv[maxk],addv[maxk]; int flag[maxk]; void push(int x) { if(!addv[x] || l[x]==r[x]) return; addv[lc(x)]+=addv[x]; addv[rc(x)]+=addv[x]; sumv[lc(x)]+=(flag[lc(x)])*addv[x]; sumv[rc(x)]+=(flag[rc(x)])*addv[x]; addv[x]=0; } inline void update(int x) { sumv[x]=sumv[lc(x)]+sumv[rc(x)]; } void add(int x,int L,int R,LL val) { if(R<l[x] || L>r[x]) return; if(L<=l[x] && r[x]<=R) { sumv[x]+=(flag[x]*val); addv[x]+=val; return; } push(x); add(lc(x),L,R,val); add(rc(x),L,R,val); update(x); } LL query(int x,int L,int R) { if(R<l[x] || L>r[x]) return 0; if(L<=l[x] && r[x]<=R) return sumv[x]; push(x); return (query(lc(x),L,R)+query(rc(x),L,R)); } void build(int x,int L,int R) { l[x]=L; r[x]=R; if(L==R) { sumv[x]=a[L]; addv[x]=0; if(down[L]) flag[x]=1; else flag[x]=-1; return; } int mid=(L+R)>>1; build(lc(x),L,mid); build(rc(x),mid+1,R); update(x); flag[x]=flag[lc(x)]+flag[rc(x)]; } }seg; void dfs(int u,int from) { a[++vid]=b[u]; down[vid]=1; in[u]=vid; for(int i=g[u];~i;i=next[i]) if(v[i]!=from) dfs(v[i],u); a[++vid]=-b[u]; out[u]=vid; down[vid]=0; } int main() { memset(g,-1,sizeof(g)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&b[i]); for(int i=1,x,y;i<n;i++) { scanf("%d%d",&x,&y); addedge(x,y); } dfs(1,0); seg.build(1,1,(n<<1)); int p,x,a; while(m--) { scanf("%d",&p); if(p==1) { scanf("%d%d",&x,&a); seg.add(1,in[x],in[x],a); seg.add(1,out[x],out[x],a); } else if(p==2) { scanf("%d%d",&x,&a); seg.add(1,in[x],out[x],a); } else { scanf("%d",&x); printf("%lld\n",seg.query(1,1,in[x])); } } return 0; }