Bzoj 4034: [HAOI2015]T2 树链剖分,子树问题,dfs序
4034: [HAOI2015]T2
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 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
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
9
13
HINT
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
会超过 10^6 。
Source
题解:
直接树链剖分。
还有处理一下子树即可。(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 }