[BZOJ4034][HAOI2015]树上操作 树链剖分

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4034

轻重链剖分,重儿子先行。树剖模版题。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 typedef long long ll;
  6 int inline readint(){
  7     int Num=0,Flag=1;char ch;
  8     while((ch=getchar())<'0'||ch>'9') if(ch=='-') break;
  9     if(ch=='-') Flag=-1; else Num=ch-'0';
 10     while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0';
 11     return Num*Flag;
 12 }
 13 int N,M,A[100010];
 14 int to[200010],ne[200010],fir[100010],cnt=0;
 15 void Add(int a,int b){
 16     to[++cnt]=b;
 17     ne[cnt]=fir[a];
 18     fir[a]=cnt;
 19 }
 20 int siz[100010],fa[100010],dep[100010],son[100010];
 21 void Dfs1(int x){
 22     siz[x]=1;
 23     son[x]=0;
 24     for(int i=fir[x];i!=-1;i=ne[i]){
 25         int v=to[i];
 26         if(v!=fa[x]){
 27             fa[v]=x;
 28             dep[v]=dep[x]+1;
 29             Dfs1(v);
 30             siz[x]+=siz[v];
 31             if(siz[v]>siz[son[x]]) son[x]=v;
 32         }
 33     }
 34 }
 35 int top[100010],in[100010],out[100010],dfn=0;
 36 void Dfs2(int x){
 37     in[x]=++dfn;
 38     if(!son[x]){
 39         out[x]=dfn;
 40         return;
 41     }
 42     top[son[x]]=top[x];
 43     Dfs2(son[x]);
 44     for(int i=fir[x];i!=-1;i=ne[i]){
 45         int v=to[i];
 46         if(v!=fa[x]&&v!=son[x]){
 47             top[v]=v;
 48             Dfs2(v);
 49         }
 50     }
 51     out[x]=dfn;
 52 }
 53 #define lson l,mid,rt<<1
 54 #define rson mid+1,r,rt<<1|1
 55 ll sum[400010],col[400010];
 56 void inline Pushup(int &rt){
 57     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
 58 }
 59 void inline Pushdown(int &rt,int len){
 60     if(col[rt]){
 61         sum[rt<<1]+=col[rt]*(len-(len>>1));
 62         sum[rt<<1|1]+=col[rt]*(len>>1);
 63         col[rt<<1]+=col[rt];
 64         col[rt<<1|1]+=col[rt];
 65         col[rt]=0;
 66     }
 67 }
 68 void Insert(int l,int r,int rt,int L,int R,ll x){
 69     if(L<=l&&r<=R){
 70         col[rt]+=x;
 71         sum[rt]+=x*(r-l+1);
 72         return;
 73     }
 74     Pushdown(rt,r-l+1);
 75     int mid=l+r>>1;
 76     if(L<=mid) Insert(lson,L,R,x);
 77     if(R>mid) Insert(rson,L,R,x);
 78     Pushup(rt);
 79 }
 80 ll Qsum(int l,int r,int rt,int L,int R){
 81     if(L<=l&&r<=R) return sum[rt];
 82     Pushdown(rt,r-l+1);
 83     int mid=l+r>>1;
 84     ll ret=0;
 85     if(L<=mid) ret=Qsum(lson,L,R);
 86     if(R>mid) ret+=Qsum(rson,L,R);
 87     return ret;
 88 }
 89 ll Qry(int x){
 90     ll ret=0;
 91     int tx=top[x];
 92     while(tx!=1){
 93         ret+=Qsum(1,N,1,in[tx],in[x]);
 94         x=fa[tx];
 95         tx=top[x];
 96     }
 97     ret+=Qsum(1,N,1,in[tx],in[x]);
 98     return ret;
 99 }
100 int main(){
101     N=readint();
102     M=readint();
103     for(int i=1;i<=N;i++) A[i]=readint();
104     memset(fir,-1,sizeof(fir));
105     for(int i=1;i<N;i++){
106         int a=readint(),
107             b=readint();
108         Add(a,b);
109         Add(b,a);
110     }
111     Dfs1(1);
112     top[1]=1;
113     Dfs2(1);
114     for(int i=1;i<=N;i++) Insert(1,N,1,in[i],in[i],A[i]);
115     for(int i=1;i<=M;i++){
116         int Opt=readint(),
117             x=readint(),a;
118         switch(Opt){
119             case 1:
120                 a=readint();
121                 Insert(1,N,1,in[x],in[x],a);
122                 break;
123             case 2:
124                 a=readint();
125                 Insert(1,N,1,in[x],out[x],a);
126                 break;
127             case 3:
128                 printf("%lld\n",Qry(x));
129                 break;
130         }
131     }
132     return 0;
133 }

 

posted @ 2017-10-18 21:27  halfrot  阅读(155)  评论(0编辑  收藏  举报