【bzoj4034】[HAOI2015]T2

siz[v]表示以v为根的子树的节点数

top[v]表示v所在的重链的顶端节点

fa[v]表示v的父亲

pos[v]表示v的父边标号

mx[v]表示v的子树中边的标号最大的那条边

 

 

参考:http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html

 

题意:

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

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

 

第一次写树链剖分。。

 

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 using namespace std;
  8  
  9 typedef long long LL;
 10  
 11 #define N 100010
 12  
 13 int id;
 14 int fa[N],siz[N],top[N];
 15 int head[N],pos[N],mx[N],v[N];
 16 LL sum[N<<2],add[N<<2];
 17  
 18 struct Node
 19 {
 20     int to,next;
 21 }e[N<<1];
 22 int cnt;
 23  
 24 int n,m;
 25 int uu,vv;
 26  
 27 int read()
 28 {
 29     int x=0,f=1;char ch=getchar();
 30     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 31     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 32     return x*f;
 33 }
 34  
 35 void link(int x,int y)
 36 {
 37     e[++cnt]=(Node){y,head[x]};
 38     head[x]=cnt;
 39 }
 40  
 41 void dfs(int x)
 42 {
 43     siz[x]=1;
 44     for (int i=head[x];i;i=e[i].next)
 45         if (e[i].to!=fa[x])
 46         {
 47             fa[e[i].to]=x;
 48             dfs(e[i].to);
 49             siz[x]+=siz[e[i].to];
 50             mx[x]=max(mx[x],mx[e[i].to]);
 51         }
 52 }
 53  
 54 void dfs2(int x,int cha)
 55 {
 56     top[x]=cha;pos[x]=mx[x]=++id;
 57     int k=0;
 58     for(int i=head[x];i;i=e[i].next)
 59         if(e[i].to!=fa[x]&&siz[e[i].to]>siz[k])
 60             k=e[i].to;
 61     if(k)
 62     {
 63         dfs2(k,cha);mx[x]=max(mx[x],mx[k]);
 64     }
 65     for(int i=head[x];i;i=e[i].next)
 66         if(e[i].to!=fa[x]&&e[i].to!=k)
 67         {
 68             dfs2(e[i].to,e[i].to);
 69             mx[x]=max(mx[x],mx[e[i].to]);
 70         }
 71 }
 72  
 73 void pushup(int now)
 74 {
 75     sum[now]=sum[now<<1]+sum[now<<1|1];
 76 }
 77  
 78 void pushdown(int nowl,int nowr,int now)
 79 {
 80     if (nowl==nowr)
 81         return;
 82     int mid=(nowl+nowr)>>1;
 83     LL t=add[now];
 84     add[now]=0;
 85     add[now<<1]+=t;
 86     add[now<<1|1]+=t;
 87     sum[now<<1]+=t*(mid-nowl+1);
 88     sum[now<<1|1]+=t*(nowr-mid);
 89 }
 90  
 91 void update(int nowl,int nowr,int now,int l,int r,LL d)
 92 {
 93     if (add[now])
 94         pushdown(nowl,nowr,now);
 95     if (nowl==l && nowr==r)
 96     {
 97         add[now]+=d;
 98         sum[now]+=(nowr-nowl+1)*d;
 99         return ;
100     }
101     int mid=(nowl+nowr)>>1;
102     if (l<=mid)
103         update(nowl,mid,now<<1,l,min(r,mid),d);
104     if (r>mid)
105         update(mid+1,nowr,now<<1|1,max(l,mid+1),r,d);
106     pushup(now);
107 }
108  
109 LL query(int nowl,int nowr,int now,int l,int r)
110 {
111     if (add[now])
112         pushdown(nowl,nowr,now);
113     if (nowl==l && nowr==r)
114         return sum[now];
115     int mid=(nowl+nowr)>>1;
116     LL ans=0;
117     if (l<=mid)
118         ans+=query(nowl,mid,now<<1,l,min(mid,r));
119     if (r>mid)
120         ans+=query(mid+1,nowr,now<<1|1,max(mid+1,l),r);
121     return ans;
122 }
123  
124 LL query(int x)
125 {
126     LL ans=0;
127     while (top[x]!=1)
128     {
129         ans+=query(1,n,1,pos[top[x]],pos[x]);
130         x=fa[top[x]];
131     }
132     ans+=query(1,n,1,1,pos[x]);
133     return ans;
134 }
135  
136 int main()
137 {
138     n=read(),m=read();
139     for (int i=1;i<=n;i++)
140         v[i]=read();
141     for (int i=1;i<n;i++)
142     {
143         uu=read(),vv=read();
144         link(uu,vv);
145         link(vv,uu);
146     }
147     dfs(1);
148     dfs2(1,1);
149     for (int i=1;i<=n;i++)
150         update(1,n,1,pos[i],pos[i],v[i]);
151     int askd,x,a;
152     while (m--)
153     {
154         askd=read(),x=read();
155         if (askd==1)
156         {
157             a=read();
158             update(1,n,1,pos[x],pos[x],a);
159         }
160         if (askd==2)
161         {
162             a=read();
163             update(1,n,1,pos[x],mx[x],a);
164         }
165         if (askd==3)
166             printf("%lld\n",query(x));
167     }
168     return 0;
169 }

 

posted @ 2016-03-28 11:56  Yangjiyuan  阅读(187)  评论(0编辑  收藏  举报