[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 }
View Code

 

posted @ 2019-07-28 10:35  PYWBKTDA  阅读(142)  评论(0编辑  收藏  举报