4034. [HAOI2015]树上操作【树链剖分】

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 。

 

一道裸的树剖却因为建树时候的sb错误搞了半天
不想说什么(不过这个题好像会炸int)

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #define LL long long
  5 #define MAXN (100000+50)
  6 using namespace std;
  7 LL Tree[MAXN];
  8 LL T_num[MAXN];
  9 LL Depth[MAXN];
 10 LL Father[MAXN];
 11 LL Sum[MAXN];
 12 LL Son[MAXN];
 13 LL Top[MAXN];
 14 LL a[MAXN];
 15 LL n,m,u,v,sum;
 16 LL head[MAXN],num_edge;
 17 struct node1
 18 {
 19     LL val;
 20     LL add;
 21 } Segt[MAXN*4];
 22 struct node2
 23 {
 24     LL to;
 25     LL next;
 26 } edge[MAXN*2];
 27 void add(LL u,LL v)
 28 {
 29     edge[++num_edge].to=v;
 30     edge[num_edge].next=head[u];
 31     head[u]=num_edge;
 32 }
 33 
 34 void Dfs1(LL x)
 35 {
 36     Sum[x]=1;
 37     Depth[x]=Depth[Father[x]]+1;
 38     for (LL i=head[x]; i!=0; i=edge[i].next)
 39         if (edge[i].to!=Father[x])
 40         {
 41             Father[edge[i].to]=x;
 42             Dfs1(edge[i].to);
 43             Sum[x]+=Sum[edge[i].to];
 44             if (Son[x]==0 || (Sum[Son[x]]<Sum[edge[i].to]))
 45                 Son[x]=edge[i].to;
 46         }
 47 }
 48 
 49 void Dfs2(LL x,LL tp)
 50 {
 51     T_num[x]=++sum;
 52     Tree[sum]=a[x];
 53     Top[x]=tp;
 54     if (Son[x])
 55         Dfs2(Son[x],tp);
 56     for (LL i=head[x]; i!=0; i=edge[i].next)
 57         if (edge[i].to!=Son[x] && edge[i].to!=Father[x])
 58             Dfs2(edge[i].to,edge[i].to);
 59 }
 60 
 61 void Pushdown(LL node,LL l,LL r)
 62 {
 63     if (Segt[node].add!=0)
 64     {
 65         LL mid=(l+r)/2;
 66         Segt[node*2].val+=Segt[node].add*(mid-l+1);
 67         Segt[node*2+1].val+=Segt[node].add*(r-mid);
 68         Segt[node*2].add+=Segt[node].add;
 69         Segt[node*2+1].add+=Segt[node].add;
 70         Segt[node].add=0;
 71     }
 72 }
 73 
 74 void Build(LL node,LL l,LL r)
 75 {
 76     if (l==r)
 77         Segt[node].val=Tree[l];
 78     else
 79     {
 80         LL mid=(l+r)/2;
 81         Build(node*2,l,mid);
 82         Build(node*2+1,mid+1,r);
 83         Segt[node].val=Segt[node*2].val+Segt[node*2+1].val;
 84     }
 85 }
 86 
 87 void Update(LL node,LL l,LL r,LL l1,LL r1,LL k)
 88 {
 89     if (l>r1 || r<l1)
 90         return;
 91     if (l1<=l && r<=r1)
 92     {
 93         Segt[node].val+=(r-l+1)*k;
 94         Segt[node].add+=k;
 95         return;
 96     }
 97     Pushdown(node,l,r);
 98     LL mid=(l+r)/2;
 99     Update(node*2,l,mid,l1,r1,k);
100     Update(node*2+1,mid+1,r,l1,r1,k);
101     Segt[node].val=Segt[node*2].val+Segt[node*2+1].val;
102 }
103 
104 LL Query(LL node,LL l,LL r,LL l1,LL r1)
105 {
106     if (l>r1 || r<l1)
107         return 0;
108     if (l1<=l && r<=r1)
109         return Segt[node].val;
110     Pushdown(node,l,r);
111     LL mid=(l+r)/2;
112     return Query(node*2,l,mid,l1,r1)+Query(node*2+1,mid+1,r,l1,r1);
113 }
114 
115 LL Get(LL x)
116 {
117     LL ans=0;
118     while (x!=0)
119     {
120         ans+=Query(1,1,n,T_num[Top[x]],T_num[x]);
121         x=Father[Top[x]];
122     }
123     return ans;
124 }
125 
126 int main()
127 {
128     scanf("%lld%lld",&n,&m);
129     for (LL i=1; i<=n; ++i)
130         scanf("%lld",&a[i]);
131     for (LL i=1; i<=n-1; ++i)
132     {
133         scanf("%lld%lld",&u,&v);
134         add(u,v);
135         add(v,u);
136     }
137     Dfs1(1);
138     Dfs2(1,1);
139     Build(1,1,n);
140     for (LL i=1; i<=m; ++i)
141     {
142         LL p,x,y;
143         scanf("%lld",&p);
144         if (p==1)
145         {
146             scanf("%lld%lld",&x,&y);
147             Update(1,1,n,T_num[x],T_num[x],y);
148         }
149         if (p==2)
150         {
151             scanf("%lld%lld",&x,&y);
152             Update(1,1,n,T_num[x],T_num[x]+Sum[x]-1,y);
153         }
154         if (p==3)
155         {
156             scanf("%lld",&x);
157             printf("%lld\n",Get(x));
158         }
159     }
160 }
posted @ 2018-03-30 22:35  Refun  阅读(141)  评论(0编辑  收藏  举报