Bzoj 4034: [HAOI2015]T2 树链剖分,子树问题,dfs序

4034: [HAOI2015]T2

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 1841  Solved: 598
[Submit][Status][Discuss]

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 。

 

Source

鸣谢bhiaibogf提供

题解:

直接树链剖分。

还有处理一下子树即可。(dfs序)。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define MAXN 100010
  4 #define LL long long
  5 struct node
  6 {
  7     int begin,end,next;
  8 }edge[2*MAXN];
  9 struct NODE
 10 {
 11     int left,right;
 12     LL sum,add;
 13 }tree[5*MAXN];
 14 int cnt,Head[MAXN],a[MAXN],size[MAXN],deep[MAXN],n,P[MAXN][17],pos[MAXN],belong[MAXN],ks[MAXN],js[MAXN],SIZE;
 15 bool vis[MAXN];
 16 void addedge(int bb,int ee)
 17 {
 18     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt;
 19 }
 20 void addedge1(int bb,int ee)
 21 {
 22     addedge(bb,ee);addedge(ee,bb);
 23 }
 24 int read()
 25 {
 26     int s=0,fh=1;char ch=getchar();
 27     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
 28     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
 29     return s*fh;
 30 }
 31 void dfs1(int u)
 32 {
 33     int i,v;
 34     size[u]=1;vis[u]=true;
 35     for(i=Head[u];i!=-1;i=edge[i].next)
 36     {
 37         v=edge[i].end;
 38         if(vis[v]==false)
 39         {
 40             deep[v]=deep[u]+1;
 41             P[v][0]=u;
 42             dfs1(v);
 43             size[u]+=size[v];
 44         }
 45     }
 46 }
 47 void Ycl()
 48 {
 49     int i,j;
 50     for(j=1;(1<<j)<=n;j++)
 51     {
 52         for(i=1;i<=n;i++)
 53         {
 54             if(P[i][j-1]!=-1)P[i][j]=P[P[i][j-1]][j-1];
 55         }
 56     }
 57 }
 58 void dfs2(int u,int chain)
 59 {
 60     int k=0,i,v;
 61     pos[u]=++SIZE;belong[u]=chain;ks[u]=SIZE;
 62     for(i=Head[u];i!=-1;i=edge[i].next)
 63     {
 64         v=edge[i].end;
 65         if(deep[v]>deep[u]&&size[v]>size[k])k=v;
 66     }
 67     if(k==0){js[u]=SIZE;return;}
 68     dfs2(k,chain);
 69     for(i=Head[u];i!=-1;i=edge[i].next)
 70     {
 71         v=edge[i].end;
 72         if(deep[v]>deep[u]&&v!=k)dfs2(v,v);
 73     }
 74     js[u]=SIZE;
 75 }
 76 void Pushup(int k)
 77 {
 78     tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
 79 }
 80 void Build(int k,int l,int r)
 81 {
 82     tree[k].left=l;tree[k].right=r;tree[k].add=0;
 83     if(l==r)return;//{tree[k].sum=a[l];return;}
 84     int mid=(l+r)/2;
 85     Build(k*2,l,mid);Build(k*2+1,mid+1,r);
 86     //Pushup(k);
 87 }
 88 /*void Pushup(int k)
 89 {
 90     tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
 91 }*/
 92 void Pushdown(int k)
 93 {
 94     int l=k*2,r=k*2+1,mid;
 95     if(tree[k].add!=0)
 96     {
 97         mid=(tree[k].left+tree[k].right)/2;
 98         tree[l].sum+=(LL)(mid-tree[k].left+1)*tree[k].add;
 99         tree[r].sum+=(LL)(tree[k].right-mid)*tree[k].add;
100         tree[l].add+=tree[k].add;
101         tree[r].add+=tree[k].add;
102         tree[k].add=0;
103     }
104 }
105 void Add(int k,int l,int r,int A)
106 {
107     if(l<=tree[k].left&&tree[k].right<=r){tree[k].add+=(LL)A;tree[k].sum+=(LL)(tree[k].right-tree[k].left+1)*A;return;}
108     Pushdown(k);
109     int mid=(tree[k].left+tree[k].right)/2;
110     if(r<=mid)Add(k*2,l,r,A);
111     else if(l>mid)Add(k*2+1,l,r,A);
112     else {Add(k*2,l,mid,A);Add(k*2+1,mid+1,r,A);}
113     Pushup(k);
114 }
115 LL Query_sum(int k,int l,int r)
116 {
117     if(l<=tree[k].left&&tree[k].right<=r)return (LL)tree[k].sum;
118     Pushdown(k);
119     int mid=(tree[k].left+tree[k].right)/2;
120     if(r<=mid)return Query_sum(k*2,l,r);
121     else if(l>mid)return Query_sum(k*2+1,l,r);
122     else return Query_sum(k*2,l,mid)+Query_sum(k*2+1,mid+1,r);
123     //Pushup(k);
124 }
125 LL Solve_sum(int x,int f)
126 {
127     LL sum=0;
128     while(belong[x]!=belong[f])
129     {
130         sum+=Query_sum(1,pos[belong[x]],pos[x]);
131         x=P[belong[x]][0];
132     }
133     sum+=Query_sum(1,pos[f],pos[x]);
134     return sum;
135 }
136 int main()
137 {
138     int m,i,bb,ee,zs,k,k1;
139     n=read();m=read();
140     for(i=1;i<=n;i++)a[i]=read();
141     memset(Head,-1,sizeof(Head));cnt=1;
142     for(i=1;i<n;i++)
143     {
144         bb=read();ee=read();
145         addedge1(bb,ee);
146     }
147     memset(P,-1,sizeof(P));SIZE=0;
148     dfs1(1);Ycl();
149     dfs2(1,1);
150     Build(1,1,n);
151     for(i=1;i<=n;i++)Add(1,pos[i],pos[i],a[i]);
152     for(i=1;i<=m;i++)
153     {
154         zs=read();
155         if(zs==1)
156         {
157             k=read();k1=read();Add(1,pos[k],pos[k],k1);
158         }
159         else if(zs==2)
160         {
161             k=read();k1=read();Add(1,ks[k],js[k],k1);
162         }
163         else
164         {
165             k=read();printf("%lld\n",Solve_sum(k,1));
166         }
167     }
168     return 0;
169 }

 

posted @ 2016-03-23 15:38  微弱的世界  阅读(215)  评论(0编辑  收藏  举报