[bzoj4034]树上操作
dfs序(注意出栈时也要加入),然后对于每一次一个节点的修改,都在左端点上打+x,右端点上打-x,区间修改同理(因此要用线段树且需要维护区间左端点数量-右端点数量)。对于询问操作,就是dfs序上的一段前缀和,用线段树处理即可。
1 #include<cstdio> 2 #include<cstring> 3 #define ll long long 4 #define maxN 100001 5 #define L (k<<1) 6 #define R ((k<<1)+1) 7 #define mid ((l+r)>>1) 8 struct ji{ 9 int next,to; 10 }edge[maxN<<1]; 11 struct node{ 12 ll k,s,lazy; 13 }f[maxN<<4]; 14 ll E,n,m,x,y,a[maxN],head[maxN],l[maxN],r[maxN]; 15 bool vis[maxN<<1]; 16 void init(){ 17 E=0; 18 memset(head,-1,sizeof(head)); 19 } 20 void add(int x,int y){ 21 edge[E].next=head[x]; 22 edge[E].to=y; 23 head[x]=E++; 24 } 25 void up(int k){ 26 f[k].k=f[L].k+f[R].k+f[k].lazy*(f[k].s=f[L].s+f[R].s); 27 } 28 void down(int k){ 29 f[L].lazy+=f[k].lazy; 30 f[L].k+=f[k].lazy*f[L].s; 31 f[R].lazy+=f[k].lazy; 32 f[R].k+=f[k].lazy*f[R].s; 33 f[k].lazy=0; 34 } 35 void update(int k,int l,int r,int x,int y,int z){ 36 if ((r<x)||(l>y))return; 37 if ((x<=l)&&(r<=y)){ 38 if (l==r) 39 if (vis[l])f[k].s=1; 40 else f[k].s=-1; 41 f[k].k+=f[k].s*z; 42 f[k].lazy+=z; 43 return; 44 } 45 update(L,l,mid,x,y,z); 46 update(R,mid+1,r,x,y,z); 47 up(k); 48 } 49 ll query(int k,int l,int r,int x,int y){ 50 if ((l>y)||(r<x))return 0; 51 if ((x<=l)&&(y>=r))return f[k].k; 52 down(k); 53 return query(L,l,mid,x,y)+query(R,mid+1,r,x,y); 54 } 55 void dfs(int k,int f){ 56 vis[l[k]=++x]=true; 57 for(int i=head[k];i!=-1;i=edge[i].next) 58 if (edge[i].to!=f)dfs(edge[i].to,k); 59 r[k]=++x; 60 } 61 int main(){ 62 int p; 63 init(); 64 scanf("%lld%lld",&n,&m); 65 for(int i=1;i<=n;i++)scanf("%lld",&a[i]); 66 for(int i=1;i<n;i++){ 67 scanf("%lld%lld",&x,&y); 68 add(x,y); 69 add(y,x); 70 } 71 x=0; 72 dfs(1,0); 73 for(int i=1;i<=n;i++){ 74 update(1,1,2*n,l[i],l[i],a[i]); 75 update(1,1,2*n,r[i],r[i],a[i]); 76 } 77 n*=2; 78 for(int i=1;i<=m;i++){ 79 scanf("%d%lld",&p,&x); 80 if (p<3)scanf("%lld",&y); 81 if (p==1){ 82 update(1,1,n,l[x],l[x],y); 83 update(1,1,n,r[x],r[x],y); 84 } 85 if (p==2)update(1,1,n,l[x],r[x],y); 86 if (p==3)printf("%lld\n",query(1,1,n,1,l[x])); 87 } 88 }