【BZOJ3611】大工程(虚树,DFS序,树形DP)
题意:有一棵树,树有边权,有若干次询问,给出一些点,求:
1.这些点互相之间的距离之和
2.点对距离中的最大和最小值
n<=1000000
q<=50000并且保证所有k之和<=2*n
思路:感谢Gold_7
建立虚树,在上面树形DP即可
最大值和最小值用了一种精妙的写法来保证是最值+次值
终于会写类似点对距离和的树形DP了
1 var head,vet,next,len, 2 head1,vet1,next1,len1, 3 h,stk,b,dep,dfn,flag,c:array[0..2100000]of longint; 4 dp:array[1..1000000,1..2]of longint; 5 size,g:array[1..1000000]of int64; 6 f:array[1..1000000,0..21]of longint; 7 n,i,tot,que,ans1,ans2,time,x,y:longint; 8 ans:int64; 9 10 procedure swap(var x,y:longint); 11 var t:longint; 12 begin 13 t:=x; x:=y; y:=t; 14 end; 15 16 function min(x,y:int64):int64; 17 begin 18 if x<y then exit(x); 19 exit(y); 20 end; 21 22 function max(x,y:int64):int64; 23 begin 24 if x>y then exit(x); 25 exit(y); 26 end; 27 28 procedure add(a,b,c:longint); 29 begin 30 inc(tot); 31 next[tot]:=head[a]; 32 vet[tot]:=b; 33 len[tot]:=c; 34 head[a]:=tot; 35 end; 36 37 procedure qsort(l,r:longint); 38 var i,j,mid:longint; 39 begin 40 i:=l; j:=r; mid:=b[(l+r)>>1]; 41 repeat 42 while mid>b[i] do inc(i); 43 while mid<b[j] do dec(j); 44 if i<=j then 45 begin 46 swap(h[i],h[j]); 47 swap(b[i],b[j]); 48 inc(i); dec(j); 49 end; 50 until i>j; 51 if l<j then qsort(l,j); 52 if i<r then qsort(i,r); 53 end; 54 55 function lca(x,y:longint):longint; 56 var i,d:longint; 57 begin 58 if dep[x]<dep[y] then swap(x,y); 59 d:=dep[x]-dep[y]; 60 for i:=0 to 21 do 61 if d and (1<<i)>0 then x:=f[x,i]; 62 for i:=21 downto 0 do 63 if f[x,i]<>f[y,i] then 64 begin 65 x:=f[x,i]; y:=f[y,i]; 66 end; 67 if x=y then exit(x); 68 exit(f[x,0]); 69 end; 70 71 procedure dfs(u:longint); 72 var e,v,i:longint; 73 begin 74 for i:=1 to 21 do 75 begin 76 if dep[u]<(1<<i) then break; 77 f[u,i]:=f[f[u,i-1],i-1]; 78 end; 79 inc(time); dfn[u]:=time; 80 flag[u]:=1; 81 e:=head[u]; 82 while e<>0 do 83 begin 84 v:=vet[e]; 85 if flag[v]=0 then 86 begin 87 f[v,0]:=u; 88 dep[v]:=dep[u]+1; 89 dfs(v); 90 end; 91 e:=next[e]; 92 end; 93 end; 94 95 procedure add1(a,b:longint); 96 begin 97 if a=b then exit; 98 inc(tot); 99 next1[tot]:=head1[a]; 100 vet1[tot]:=b; 101 len1[tot]:=abs(dep[a]-dep[b]); 102 head1[a]:=tot; 103 end; 104 105 procedure dfs2(u:longint); 106 var e,v:longint; 107 begin 108 size[u]:=c[u]; 109 g[u]:=0; 110 if c[u]=1 then begin dp[u,1]:=0; dp[u,2]:=0; end 111 else begin dp[u,1]:=-maxlongint div 3; dp[u,2]:=maxlongint div 3; end; 112 e:=head1[u]; 113 while e<>0 do 114 begin 115 v:=vet1[e]; 116 dfs2(v); 117 ans:=ans+size[v]*g[u]+size[u]*g[v]+size[u]*size[v]*len1[e]; 118 size[u]:=size[u]+size[v]; 119 g[u]:=g[u]+g[v]+size[v]*len1[e]; 120 ans1:=max(ans1,dp[u,1]+dp[v,1]+len1[e]); 121 ans2:=min(ans2,dp[u,2]+dp[v,2]+len1[e]); 122 dp[u,1]:=max(dp[u,1],dp[v,1]+len1[e]); 123 dp[u,2]:=min(dp[u,2],dp[v,2]+len1[e]); 124 e:=next1[e]; 125 end; 126 head1[u]:=0; 127 end; 128 129 procedure solve; 130 var q,top,i,now,m,p:longint; 131 begin 132 tot:=0; 133 read(m); 134 for i:=1 to m do 135 begin 136 read(h[i]); b[i]:=dfn[h[i]]; 137 c[h[i]]:=1; 138 end; 139 qsort(1,m); 140 //q:=1; 141 //for i:=2 to m do 142 //if lca(h[i],h[q])<>h[q] then begin inc(q); h[q]:=h[i]; end; 143 stk[1]:=1; top:=1; 144 for i:=1 to m do 145 begin 146 now:=h[i]; p:=lca(now,stk[top]); 147 while true do 148 begin 149 if dep[p]>=dep[stk[top-1]] then 150 begin 151 add1(p,stk[top]); dec(top); 152 if stk[top]<>p then begin inc(top); stk[top]:=p; end; 153 break; 154 end; 155 add1(stk[top-1],stk[top]); dec(top); 156 end; 157 if stk[top]<>now then begin inc(top); stk[top]:=now; end; 158 end; 159 for i:=top-1 downto 1 do add1(stk[i],stk[i+1]); 160 ans:=0; ans1:=-maxlongint div 3; ans2:=maxlongint div 3; 161 dfs2(1); 162 writeln(ans,' ',ans2,' ',ans1); 163 for i:=1 to m do c[h[i]]:=0; 164 end; 165 166 167 begin 168 169 readln(n); 170 for i:=1 to n-1 do 171 begin 172 readln(x,y); 173 add(x,y,1); 174 add(y,x,1); 175 end; 176 dfs(1); 177 readln(que); 178 for i:=1 to que do solve; 179 180 end.
%了XYZ(虚树发明者)论文后的新的建虚树方法,简明易懂:
1:加入所有原关键点并按DFS序排序
2:将排序后两两相邻点对的LCA加入后去重,并再次排序
3:将第二次排序后的点依次入栈,若栈顶元素y非插入元素x的祖先则退栈,直到栈顶元素为x的祖先为止,链接x,y
1 var head,vet,next,len, 2 head1,vet1,next1,len1, 3 h,stk,b,dep,dfn,flag,c,d:array[0..2100000]of longint; 4 dp:array[1..1000000,1..2]of longint; 5 size,g:array[1..1000000]of int64; 6 f:array[1..1000000,0..21]of longint; 7 n,i,tot,que,ans1,ans2,time,x,y:longint; 8 ans:int64; 9 10 procedure swap(var x,y:longint); 11 var t:longint; 12 begin 13 t:=x; x:=y; y:=t; 14 end; 15 16 function min(x,y:int64):int64; 17 begin 18 if x<y then exit(x); 19 exit(y); 20 end; 21 22 function max(x,y:int64):int64; 23 begin 24 if x>y then exit(x); 25 exit(y); 26 end; 27 28 procedure add(a,b,c:longint); 29 begin 30 inc(tot); 31 next[tot]:=head[a]; 32 vet[tot]:=b; 33 len[tot]:=c; 34 head[a]:=tot; 35 end; 36 37 procedure qsort1(l,r:longint); 38 var i,j,mid:longint; 39 begin 40 i:=l; j:=r; mid:=b[(l+r)>>1]; 41 repeat 42 while mid>b[i] do inc(i); 43 while mid<b[j] do dec(j); 44 if i<=j then 45 begin 46 swap(h[i],h[j]); 47 swap(b[i],b[j]); 48 inc(i); dec(j); 49 end; 50 until i>j; 51 if l<j then qsort1(l,j); 52 if i<r then qsort1(i,r); 53 end; 54 55 procedure qsort2(l,r:longint); 56 var i,j,mid:longint; 57 begin 58 i:=l; j:=r; mid:=b[(l+r)>>1]; 59 repeat 60 while mid>b[i] do inc(i); 61 while mid<b[j] do dec(j); 62 if i<=j then 63 begin 64 swap(d[i],d[j]); 65 swap(b[i],b[j]); 66 inc(i); dec(j); 67 end; 68 until i>j; 69 if l<j then qsort2(l,j); 70 if i<r then qsort2(i,r); 71 end; 72 73 function lca(x,y:longint):longint; 74 var i,d:longint; 75 begin 76 if dep[x]<dep[y] then swap(x,y); 77 d:=dep[x]-dep[y]; 78 for i:=0 to 21 do 79 if d and (1<<i)>0 then x:=f[x,i]; 80 for i:=21 downto 0 do 81 if f[x,i]<>f[y,i] then 82 begin 83 x:=f[x,i]; y:=f[y,i]; 84 end; 85 if x=y then exit(x); 86 exit(f[x,0]); 87 end; 88 89 procedure dfs(u:longint); 90 var e,v,i:longint; 91 begin 92 for i:=1 to 21 do 93 begin 94 if dep[u]<(1<<i) then break; 95 f[u,i]:=f[f[u,i-1],i-1]; 96 end; 97 inc(time); dfn[u]:=time; 98 flag[u]:=1; 99 e:=head[u]; 100 while e<>0 do 101 begin 102 v:=vet[e]; 103 if flag[v]=0 then 104 begin 105 f[v,0]:=u; 106 dep[v]:=dep[u]+1; 107 dfs(v); 108 end; 109 e:=next[e]; 110 end; 111 end; 112 113 procedure add1(a,b:longint); 114 begin 115 if a=b then exit; 116 inc(tot); 117 next1[tot]:=head1[a]; 118 vet1[tot]:=b; 119 len1[tot]:=abs(dep[a]-dep[b]); 120 head1[a]:=tot; 121 end; 122 123 procedure dfs2(u:longint); 124 var e,v:longint; 125 begin 126 size[u]:=c[u]; 127 g[u]:=0; 128 if c[u]=1 then begin dp[u,1]:=0; dp[u,2]:=0; end 129 else begin dp[u,1]:=-maxlongint div 3; dp[u,2]:=maxlongint div 3; end; 130 e:=head1[u]; 131 while e<>0 do 132 begin 133 v:=vet1[e]; 134 dfs2(v); 135 ans:=ans+size[v]*g[u]+size[u]*g[v]+size[u]*size[v]*len1[e]; 136 size[u]:=size[u]+size[v]; 137 g[u]:=g[u]+g[v]+size[v]*len1[e]; 138 ans1:=max(ans1,dp[u,1]+dp[v,1]+len1[e]); 139 ans2:=min(ans2,dp[u,2]+dp[v,2]+len1[e]); 140 dp[u,1]:=max(dp[u,1],dp[v,1]+len1[e]); 141 dp[u,2]:=min(dp[u,2],dp[v,2]+len1[e]); 142 e:=next1[e]; 143 end; 144 head1[u]:=0; 145 end; 146 147 procedure solve; 148 var q,top,i,now,m,p:longint; 149 begin 150 tot:=0; 151 read(m); 152 for i:=1 to m do 153 begin 154 read(h[i]); b[i]:=dfn[h[i]]; 155 c[h[i]]:=1; 156 end; 157 qsort1(1,m); 158 q:=0; 159 for i:=1 to m do 160 begin 161 inc(q); d[q]:=h[i]; flag[h[i]]:=1; 162 end; 163 for i:=1 to m-1 do 164 begin 165 p:=lca(h[i],h[i+1]); 166 if flag[p]=0 then begin flag[p]:=1; inc(q); d[q]:=p; end; 167 end; 168 for i:=1 to q do b[i]:=dfn[d[i]]; 169 qsort2(1,q); 170 171 stk[1]:=d[1]; top:=1; 172 for i:=2 to q do 173 begin 174 x:=d[i]; 175 while true do 176 begin 177 y:=stk[top]; 178 if lca(x,y)<>y then dec(top) 179 else 180 begin 181 add1(y,x); 182 break; 183 end; 184 end; 185 inc(top); stk[top]:=x; 186 end; 187 188 189 ans:=0; ans1:=-maxlongint div 3; ans2:=maxlongint div 3; 190 dfs2(d[1]); 191 writeln(ans,' ',ans2,' ',ans1); 192 for i:=1 to m do c[h[i]]:=0; 193 for i:=1 to q do flag[d[i]]:=0; 194 end; 195 196 197 begin 198 assign(input,'bzoj3611.in'); reset(input); 199 assign(output,'bzoj3611.out'); rewrite(output); 200 readln(n); 201 for i:=1 to n-1 do 202 begin 203 readln(x,y); 204 add(x,y,1); 205 add(y,x,1); 206 end; 207 dfs(1); 208 readln(que); 209 fillchar(flag,sizeof(flag),0); 210 for i:=1 to que do solve; 211 close(input); 212 close(output); 213 end.
null