bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015)
题目大意
给定一颗树,1为根节点,要求支持三种操作。
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
解题分析
练手题。树链剖分+线段树。
参考程序
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 7 #define V 100008 8 #define E 200008 9 #define lson l,m,rt << 1 10 #define rson m+1,r,rt << 1 | 1 11 #define LL long long 12 13 struct line{ 14 int u,v,w,nt; 15 }eg[E]; 16 int sum,lt[V]; 17 18 void adt(int u,int v){ 19 eg[++sum].u=u; eg[sum].v=v; eg[sum].nt=lt[u]; lt[u]=sum; 20 } 21 void add(int u,int v){ 22 adt(u,v); adt(v,u); 23 } 24 25 int size[V],fa[V],dep[V],son[V],w[V],top[V],rk[V]; 26 int n,m,a[V],cnt; 27 28 void dfs_1(int u){ 29 size[u]=1; dep[u]=dep[fa[u]]+1; son[u]=0; 30 for (int i=lt[u];i;i=eg[i].nt){ 31 int v=eg[i].v; 32 if (v==fa[u]) continue; 33 fa[v]=u; 34 dfs_1(v); 35 size[u]+=size[v]; 36 if (size[v]>size[son[u]]) son[u]=v; 37 } 38 } 39 40 void dfs_2(int u,int tp){ 41 top[u]=tp; w[u]=++cnt; rk[cnt]=u; 42 if (son[u]) dfs_2(son[u],tp); 43 for (int i=lt[u];i;i=eg[i].nt){ 44 int v=eg[i].v; 45 if (v==fa[u] || v==son[u]) continue; 46 dfs_2(v,v); 47 } 48 } 49 50 struct segment_tree{ 51 LL sum[V << 2],lazy[V << 2]; 52 void pushup(int rt){ 53 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 54 } 55 void pushdown(int rt,int m){ 56 if (lazy[rt]){ 57 lazy[rt<<1]+=lazy[rt]; 58 lazy[rt<<1|1]+=lazy[rt]; 59 sum[rt<<1]+=lazy[rt] * (m-m/2); 60 sum[rt<<1|1]+=lazy[rt] * (m/2); 61 lazy[rt]=0; 62 } 63 } 64 void build(int l,int r,int rt){ 65 lazy[rt]=0; 66 if (l==r){ 67 sum[rt]=a[rk[l]]; 68 return; 69 } 70 int m=(l+r)/2; 71 build(lson); 72 build(rson); 73 pushup(rt); 74 } 75 void update(int L,int R,int val,int l,int r,int rt){ 76 if (L<=l && r<=R){ 77 lazy[rt]+=val; 78 sum[rt]+=1ll*(r-l+1)*val; 79 return; 80 } 81 pushdown(rt,r-l+1); 82 int m=(l+r)/2; 83 if (L <= m) update(L,R,val,lson); 84 if (m < R) update(L,R,val,rson); 85 pushup(rt); 86 } 87 LL query(int L,int R,int l,int r,int rt){ 88 if (L<=l && r<=R){ 89 return sum[rt]; 90 } 91 pushdown(rt,r-l+1); 92 int m=(l+r)/2; 93 LL res=0; 94 if (L <= m) res+=query(L,R,lson); 95 if (m < R) res+=query(L,R,rson); 96 return res; 97 } 98 }T; 99 100 void change(int x,int y){ 101 LL res=0; 102 while (top[x]!=top[y]){ 103 if (dep[top[x]]<dep[top[y]]) swap(x,y); 104 res+=T.query(w[top[x]],w[x],1,n,1); 105 x=fa[top[x]]; 106 } 107 if (dep[x]>dep[y]) swap(x,y); 108 res+=T.query(w[x],w[y],1,n,1); 109 printf("%lld\n",res ); 110 } 111 112 int main(){ 113 memset(lt,0,sizeof(lt)); sum=1; 114 scanf("%d %d",&n,&m); 115 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 116 for (int i=1;i<n;i++){ 117 int u,v; 118 scanf("%d %d",&u,&v); 119 add(u,v); 120 } 121 dfs_1(1); 122 dfs_2(1,1); 123 T.build(1,n,1); 124 while (m--){ 125 int x,y,z; 126 scanf("%d",&x); 127 if (x==1){ 128 scanf("%d %d",&y,&z); 129 T.update(w[y],w[y],z,1,n,1); 130 } 131 if (x==2){ 132 scanf("%d %d",&y,&z); 133 T.update(w[y],w[y]+size[y]-1,z,1,n,1); 134 } 135 if (x==3){ 136 scanf("%d",&y); 137 change(1,y); 138 } 139 } 140 }