数据结构(树链剖分):BZOJ 4034: [HAOI2015]T2

Description

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

操作,分为三种:
  操作 1 :把某个节点 x 的点权增加 a 。
  操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
  操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
 

Input

  第一行包含两个整数 N, M 。表示点数和操作数。

  接下来一行 N 个整数,表示树中节点的初始权值。
  接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
  再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
  作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
 

Output

   对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

 

Sample Input

5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3

Sample Output

6
9
13

HINT

   对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不

会超过 10^6 。
 
  
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 using namespace std;
  6 const int maxn=100010;
  7 int cnt,fir[maxn],to[maxn<<1],nxt[maxn<<1],n,m;
  8 void addedge(int a,int b){
  9     nxt[++cnt]=fir[a];to[cnt]=b;fir[a]=cnt;
 10 }
 11 long long key[maxn],tr[maxn<<2],add[maxn<<2];
 12 int ID[maxn],fa[maxn],top[maxn],end[maxn],sz[maxn],son[maxn];
 13 void Push_up(int x){
 14     tr[x]=tr[x<<1]+tr[x<<1|1];
 15 }
 16 void Add(int x,int l,int r,long long d){
 17     tr[x]+=(r-l+1)*d;
 18     add[x]+=d;
 19 }
 20 void Push_down(int x,int l,int r){
 21     if(add[x]){
 22         int mid=(l+r)>>1;
 23         Add(x<<1,l,mid,add[x]);
 24         Add(x<<1|1,mid+1,r,add[x]);
 25         add[x]=0;
 26     }
 27 }
 28 void Updata(int node,int l,int r,int a,int b,long long d){
 29     if(l>=a&&r<=b){
 30         Add(node,l,r,d);
 31         return;
 32     }
 33     Push_down(node,l,r);
 34     int mid=(l+r)>>1;
 35     if(mid>=a)Updata(node<<1,l,mid,a,b,d);
 36     if(mid<b) Updata(node<<1|1,mid+1,r,a,b,d);
 37     Push_up(node);
 38 }
 39 long long Query(int node,int l,int r,int a,int b){
 40     if(l>=a&&r<=b)return tr[node];
 41     Push_down(node,l,r);
 42     int mid=(l+r)>>1;
 43     long long ret=0;
 44     if(mid>=a)ret=Query(node<<1,l,mid,a,b);
 45     if(mid<b) ret+=Query(node<<1|1,mid+1,r,a,b);
 46     return ret;
 47 }
 48 void DFS(int x){
 49     sz[x]=1;
 50     for(int i=fir[x];i;i=nxt[i]){
 51         if(to[i]==fa[x])continue;
 52         fa[to[i]]=x;
 53         DFS(to[i]);
 54         sz[x]+=sz[to[i]];
 55         son[x]=sz[son[x]]<sz[to[i]]?to[i]:son[x];
 56     }
 57 }
 58 long long Solve(int y){
 59     long long ret=0;
 60     while(y){
 61         ret+=Query(1,1,n,ID[top[y]],ID[y]);
 62         y=fa[top[y]];
 63     }    
 64     return ret;
 65 }    
 66 int cont;
 67 void DFS2(int x,int tp){
 68     ID[x]=++cont;top[x]=tp;
 69     if(son[x])DFS2(son[x],tp);
 70     for(int i=fir[x];i;i=nxt[i])
 71         if(to[i]!=fa[x]&&to[i]!=son[x])
 72             DFS2(to[i],to[i]);
 73     end[x]=cont;        
 74 }    
 75 int main(){
 76     freopen("t2.in","r",stdin);
 77     freopen("t2.out","w",stdout);
 78     scanf("%d %d",&n,&m);
 79     for(int i=1;i<=n;i++)
 80         scanf("%lld",&key[i]);
 81         
 82     for(int i=1,a,b;i<n;i++){
 83         scanf("%d %d",&a,&b);
 84         addedge(a,b);
 85         addedge(b,a);
 86     }    
 87 
 88     DFS(1);
 89     DFS2(1,1);
 90 
 91     for(int i=1;i<=n;i++)
 92         Updata(1,1,n,ID[i],ID[i],key[i]);
 93     int op,x,a;
 94     while(m--){
 95         scanf("%d",&op);
 96         if(op==1){
 97             scanf("%d%d",&x,&a);
 98             Updata(1,1,n,ID[x],ID[x],a);
 99         }
100         else if(op==2){
101             scanf("%d%d",&x,&a);
102             Updata(1,1,n,ID[x],end[x],a);
103         }
104         else{
105             scanf("%d",&x);
106             printf("%lld\n",Solve(x));
107         }
108     }
109     return 0;
110 }

 

posted @ 2016-03-30 14:18  TenderRun  阅读(293)  评论(0编辑  收藏  举报