题意:有一棵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四个点对取最大值

然而我懒得写了

 const mo=;
var g:array[..,..]of int64;
h:array[..,..]of longint;
fa,cx,cy,b,ff:array[..]of longint;
f,a,ans:array[..]of int64;
head,vet,next:array[..]of longint;
n,i,x,y,tot:longint;
t:int64; procedure add(a,b:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
head[a]:=tot;
end; function max(x,y:int64):int64;
begin
if x>y then exit(x);
exit(y);
end; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; procedure dfs(u,pre:longint);
var e,v:longint;
begin
e:=head[u];
while e<> do
begin
v:=vet[e];
if v<>pre then
begin
ff[v]:=u;
dfs(v,u);
end;
e:=next[e];
end;
end; function mi(x,y:int64):int64;
var tmp:int64;
begin
mi:=; tmp:=x;
while y> do
begin
if y and = then mi:=mi*tmp mod mo;
tmp:=tmp*tmp mod mo;
y:=y>>;
end;
end; function exf(x:int64):int64;
begin
exit(mi(x,mo-));
end; begin
assign(input,'forest.in'); reset(input);
assign(output,'forest.out'); rewrite(output);
readln(n);
for i:= to n do
begin
read(a[i]);
f[i]:=a[i];
end;
for i:= to n- do
begin
read(cx[i],cy[i]);
add(cx[i],cy[i]);
add(cy[i],cx[i]);
end;
for i:= to n- do read(b[i]);
dfs(,-);
t:=;
for i:= to n do t:=t*a[i] mod mo;
ans[n]:=t;
for i:=n- downto do
begin
x:=cx[b[i]]; y:=cy[b[i]];
if ff[y]<>x then swap(x,y);
t:=t*exf(f[y]) mod mo;
fa[y]:=x;
while x> do
begin
if fa[x]= then t:=t*exf(f[x]) mod mo;
f[x]:=max(f[x],f[y]);
if g[y,]+a[y]>g[x,] then
begin
if h[x,]<>y then
begin
g[x,]:=g[x,]; h[x,]:=h[x,];
end;
g[x,]:=g[y,]+a[y];
h[x,]:=y;
end
else if (g[y,]+a[y]>g[x,])and(y<>h[x,]) then
begin
g[x,]:=g[y,]+a[y];
h[x,]:=y;
end;
f[x]:=max(f[x],g[x,]+g[x,]+a[x]);
y:=x; x:=fa[x];
end;
t:=t*f[y] mod mo;
ans[i]:=t;
end;
for i:= to n do writeln(ans[i]); close(input);
close(output);
end.

最新文章

  1. jQuery 获取 radio 选中后的文字
  2. 用jQuery Mobile做HTML5移动应用的三个优缺点
  3. Linux Linux程序练习十五(进程间的通信共享内存版)
  4. Oracle 列顺序测试
  5. C#中的反射 Assembly.Load() Assembly.LoadFrom()
  6. Beyond Compare 设置打开文件的默认编码
  7. JAVA中IO和NIO的详解分析,内容来自网络和自己总结
  8. 网站静态化处理—web前端优化—下【终篇】(13)
  9. 记录WEUI中滚动加载的一个BUG
  10. javascript隐式原型
  11. js实现多标签页效果
  12. IntelliJ IDEA(2018)安装详解
  13. MySQL------报错Access denied for user &#39;root&#39;@&#39;localhost&#39; (using password:NO)解决方法
  14. vue render function
  15. elasticsearch 第一篇(入门篇)
  16. js生成二维码的jquery组件–qrcode
  17. 17.Delete Methods-官方文档摘录
  18. 剑指Offer——最长不包含重复字符的子字符串
  19. Mastache.js学习笔记(转自小花喵)
  20. ie8下input文字偏上select文字偏下

热门文章

  1. Html5的等学习
  2. Nuget使用备忘
  3. C# 获取Google Chrome的书签
  4. vue 前端判断输入框不能输入0 空格。特殊符号。
  5. 控件中添加的成员变量value和control的区别
  6. 201621123080《java程序设计》第14周实验总结
  7. Re:从零开始的Linux之路(目录配置)
  8. 【mac】【php】mac php开机重启
  9. 14-15.Yii2.0模型的创建/读取数据使用,框架防止sql注入
  10. selenium+phantomjs爬取京东商品信息