【BZOJ4034】T2(树链剖分)
题意:
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
会超过 10^6。
思路:
因为以X为根中的子树分成了一条条重链,而他们的编号是连续的。
所以我们可以在DFS2时找到以x为根时它的子树在线段树中的最大编号mx[x]。
然后就是裸地区间修改和求和。
1 var t:array[1..500000]of record 2 a,s:int64; 3 end; 4 head,vet,next,top,tid,mx,fa,size,a,son,flag,dep,id:array[0..200000]of longint; 5 n,m,i,x,y,tot,time,ch:longint; 6 7 procedure add(a,b:longint); 8 begin 9 inc(tot); 10 next[tot]:=head[a]; 11 vet[tot]:=b; 12 head[a]:=tot; 13 end; 14 15 function max(x,y:longint):longint; 16 begin 17 if x>y then exit(x); 18 exit(y); 19 end; 20 21 procedure dfs1(u:longint); 22 var e,maxsize,v:longint; 23 begin 24 flag[u]:=1; size[u]:=1; 25 e:=head[u]; son[u]:=0; maxsize:=0; 26 while e<>0 do 27 begin 28 v:=vet[e]; 29 if flag[v]=0 then 30 begin 31 fa[v]:=u; dep[v]:=dep[u]+1; 32 dfs1(v); 33 size[u]:=size[u]+size[v]; 34 if size[v]>maxsize then 35 begin 36 maxsize:=size[v]; 37 son[u]:=v; 38 end; 39 end; 40 e:=next[e]; 41 end; 42 end; 43 44 procedure dfs2(u,ance:longint); 45 var e,v:longint; 46 begin 47 flag[u]:=1; inc(time); tid[u]:=time; id[time]:=u; top[u]:=ance; 48 mx[u]:=time; 49 if son[u]>0 then 50 begin 51 dfs2(son[u],ance); 52 mx[u]:=max(mx[u],mx[son[u]]); 53 end; 54 e:=head[u]; 55 while e<>0 do 56 begin 57 v:=vet[e]; 58 if flag[v]=0 then 59 begin 60 dfs2(v,v); 61 mx[u]:=max(mx[u],mx[v]); 62 end; 63 e:=next[e]; 64 end; 65 end; 66 67 procedure build(l,r,p:longint); 68 var mid:longint; 69 begin 70 if l=r then 71 begin 72 t[p].s:=a[id[l]]; 73 exit; 74 end; 75 mid:=(l+r)>>1; 76 build(l,mid,p<<1); 77 build(mid+1,r,p<<1+1); 78 t[p].s:=t[p<<1].s+t[p<<1+1].s; 79 end; 80 81 procedure update(l,r,x,y:longint;v:int64;p:longint); 82 var mid:longint; 83 begin 84 if (l>=x)and(r<=y) then 85 begin 86 t[p].a:=t[p].a+v; 87 t[p].s:=t[p].s+v*(r-l+1); 88 exit; 89 end; 90 mid:=(l+r)>>1; 91 t[p<<1].a:=t[p<<1].a+t[p].a; 92 t[p<<1+1].a:=t[p<<1+1].a+t[p].a; 93 t[p<<1].s:=t[p<<1].s+(mid-l+1)*t[p].a; 94 t[p<<1+1].s:=t[p<<1+1].s+(r-mid)*t[p].a; 95 t[p].a:=0; 96 if x<=mid then update(l,mid,x,y,v,p<<1); 97 if y>mid then update(mid+1,r,x,y,v,p<<1+1); 98 t[p].s:=t[p<<1].s+t[p<<1+1].s; 99 end; 100 101 function query(l,r,x,y,p:longint):int64; 102 var mid:longint; 103 tt:int64; 104 begin 105 if (l>=x)and(r<=y) then exit(t[p].s); 106 mid:=(l+r)>>1; 107 t[p<<1].a:=t[p<<1].a+t[p].a; 108 t[p<<1+1].a:=t[p<<1+1].a+t[p].a; 109 t[p<<1].s:=t[p<<1].s+(mid-l+1)*t[p].a; 110 t[p<<1+1].s:=t[p<<1+1].s+(r-mid)*t[p].a; 111 t[p].a:=0; 112 tt:=0; 113 if x<=mid then tt:=tt+query(l,mid,x,y,p<<1); 114 if y>mid then tt:=tt+query(mid+1,r,x,y,p<<1+1); 115 exit(tt); 116 end; 117 118 function ask(x:longint):int64; 119 var t:int64; 120 begin 121 t:=0; 122 while top[x]<>1 do 123 begin 124 t:=t+query(1,n,tid[top[x]],tid[x],1); 125 x:=fa[top[x]]; 126 end; 127 t:=t+query(1,n,1,tid[x],1); 128 exit(t); 129 end; 130 131 begin 132 assign(input,'bzoj4034.in'); reset(input); 133 assign(output,'bzoj4034.out'); rewrite(output); 134 readln(n,m); 135 for i:=1 to n do read(a[i]); 136 for i:=1 to n-1 do 137 begin 138 readln(x,y); 139 add(x,y); 140 add(y,x); 141 end; 142 dfs1(1); 143 fillchar(flag,sizeof(flag),0); 144 dfs2(1,1); 145 build(1,n,1); 146 147 for i:=1 to m do 148 begin 149 read(ch); 150 case ch of 151 1: 152 begin 153 read(x,y); 154 update(1,n,tid[x],tid[x],y,1); 155 end; 156 2: 157 begin 158 read(x,y); 159 update(1,n,tid[x],mx[x],y,1); 160 end; 161 3: 162 begin 163 read(x); 164 writeln(ask(x)); 165 end; 166 end; 167 end; 168 close(input); 169 close(output); 170 end.
null