题意:有一棵N个点的树,每个点上有点权
定义路径长度为所经过的所有点的点权之和,树的直径为一棵树中最大的路径长度
有N次询问,每次询问要求回答所有树的直径之积
每次询问后会删一条边,树的数量会+1
要求回答N次询问,答案 mod 10^9+7
n<=100000
思路:因为知道每次删哪条边所以可以离线倒着做,每次加一条边
加边会使两棵树合并,考虑树的合并
已知原树的形状,可知点之间的父子关系
考虑DP,设dp[u,1],dp[u,2]为以U为根,子树中路径的最长与次长值,同时记录从哪个儿子取到
f[u]为以U为根的子树中的路径最大长度
注意最长与次长必须由两个不同的儿子转移来,更新时注意
对于ans[i]要合并X与Y,在原树中它们必定是父子关系
设X为Y的父亲
新的ANS就是旧的ans/旧的f[y]*新的f[合并后子树的根,即X的最上层根节点]
向上递归即可
出现除法取模,使用费马小定理求逆元
a^(p-2)=a^-1 (mod p)
题解方法是暴力+倍增优化,直径由U1,V1,U2,V2四个点对取最大值
然而我懒得写了
1 const mo=1000000007; 2 var g:array[1..100000,1..2]of int64; 3 h:array[1..100000,1..2]of longint; 4 fa,cx,cy,b,ff:array[1..100000]of longint; 5 f,a,ans:array[1..100000]of int64; 6 head,vet,next:array[1..300000]of longint; 7 n,i,x,y,tot:longint; 8 t:int64; 9 10 procedure add(a,b:longint); 11 begin 12 inc(tot); 13 next[tot]:=head[a]; 14 vet[tot]:=b; 15 head[a]:=tot; 16 end; 17 18 function max(x,y:int64):int64; 19 begin 20 if x>y then exit(x); 21 exit(y); 22 end; 23 24 procedure swap(var x,y:longint); 25 var t:longint; 26 begin 27 t:=x; x:=y; y:=t; 28 end; 29 30 procedure dfs(u,pre:longint); 31 var e,v:longint; 32 begin 33 e:=head[u]; 34 while e<>0 do 35 begin 36 v:=vet[e]; 37 if v<>pre then 38 begin 39 ff[v]:=u; 40 dfs(v,u); 41 end; 42 e:=next[e]; 43 end; 44 end; 45 46 function mi(x,y:int64):int64; 47 var tmp:int64; 48 begin 49 mi:=1; tmp:=x; 50 while y>0 do 51 begin 52 if y and 1=1 then mi:=mi*tmp mod mo; 53 tmp:=tmp*tmp mod mo; 54 y:=y>>1; 55 end; 56 end; 57 58 function exf(x:int64):int64; 59 begin 60 exit(mi(x,mo-2)); 61 end; 62 63 begin 64 assign(input,‘forest.in‘); reset(input); 65 assign(output,‘forest.out‘); rewrite(output); 66 readln(n); 67 for i:=1 to n do 68 begin 69 read(a[i]); 70 f[i]:=a[i]; 71 end; 72 for i:=1 to n-1 do 73 begin 74 read(cx[i],cy[i]); 75 add(cx[i],cy[i]); 76 add(cy[i],cx[i]); 77 end; 78 for i:=1 to n-1 do read(b[i]); 79 dfs(1,-1); 80 t:=1; 81 for i:=1 to n do t:=t*a[i] mod mo; 82 ans[n]:=t; 83 for i:=n-1 downto 1 do 84 begin 85 x:=cx[b[i]]; y:=cy[b[i]]; 86 if ff[y]<>x then swap(x,y); 87 t:=t*exf(f[y]) mod mo; 88 fa[y]:=x; 89 while x>0 do 90 begin 91 if fa[x]=0 then t:=t*exf(f[x]) mod mo; 92 f[x]:=max(f[x],f[y]); 93 if g[y,1]+a[y]>g[x,1] then 94 begin 95 if h[x,1]<>y then 96 begin 97 g[x,2]:=g[x,1]; h[x,2]:=h[x,1]; 98 end; 99 g[x,1]:=g[y,1]+a[y]; 100 h[x,1]:=y; 101 end 102 else if (g[y,1]+a[y]>g[x,2])and(y<>h[x,1]) then 103 begin 104 g[x,2]:=g[y,1]+a[y]; 105 h[x,2]:=y; 106 end; 107 f[x]:=max(f[x],g[x,1]+g[x,2]+a[x]); 108 y:=x; x:=fa[x]; 109 end; 110 t:=t*f[y] mod mo; 111 ans[i]:=t; 112 end; 113 for i:=1 to n do writeln(ans[i]); 114 115 close(input); 116 close(output); 117 end.
时间: 2024-10-23 11:46:17