发现可以直接建立虚树。

设 \(dp_{u,0/1/2}\) 表示第 \(u\) 个节点的子树内,所有选中节点到它的距离之和/选中节点中到它的最短距离/选中节点中到它的最长距离,\(as_{u,0/1/2}\) 则代表对于这个子树,题目所问问题的三个答案,\(i1,i2\) 分别为使 \(dp_{u,1/2}\) 取极值的 \(v\)。

则 \(dp\) 方程为:

\[dp_{u,0}=\sum\limits_{v\in uson}dis(u,v)\times sz_v+dp_{0,v}
\]
\[dp_{u,1}=\min\limits_{v\in uson}dp_{v,1}+dis(u,v)
\]
\[dp_{u,2}=\max\limits_{v\in uson}dp_{v,2}+dis(u,v)
\]
\[as_{u,0}=\sum\limits_{v\in uson}as_{v,0}+(dis(u,v)\times sz_v+dp_{v,0})(sz_x-sz_y)
\]
\[as_{u,1}=\min(\min\limits_{v\in uson}as_{v,1},\min\limits_{v\in uson且i1\ne v}dp_{u,1}+dp_{v,1}+dis(u,v))
\]
\[as_{u,2}=\max(\max\limits_{v\in uson}as_{v,2},\max\limits_{v\in uson且i2\ne v}dp_{u,2}+dp_{v,2}+dis(u,v))
\]

时间复杂度 \(O(\sum k\log k)\)。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1000005;
int n,l,q,dfn[N],fa[N][21],p[N],a[N];
int m,r,t,k,h[N],nxt[N*2],to[N*2];
int d[N],nex[N*2],go[N*2],dep[N],b[N*2];
ll dp[3][N],as[3][N],c[N*2],sz[N];
int cmp(int x,int y){
return dfn[x]<dfn[y];
}void ad(int x,int y){
to[++m]=y;nxt[m]=h[x];h[x]=m;
}void add(int x,int y,int z){
go[++r]=y;c[r]=z;
nex[r]=d[x];d[x]=r;
}void dfs(int x,int f){
dep[x]=dep[f]+1;
fa[x][0]=f;dfn[x]=++l;
for(int i=0;i<20;i++)
fa[x][i+1]=fa[fa[x][i]][i];
for(int i=h[x];i;i=nxt[i])
if(f!=to[i]) dfs(to[i],x);
}int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=20;~i;i--)
if(dep[x]-dep[y]>=(1<<i))
x=fa[x][i];
if(x==y) return x;
for(int i=20;~i;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}int dis(int x,int y){
return dep[x]+dep[y]-2*dep[lca(x,y)];
}void dp_(int x,int f){
ll i1=0,i2=0;
as[1][x]=1e18;
if(p[x]==2) sz[x]=1;
else dp[1][x]=1e18;
for(int i=d[x];i;i=nex[i]){
int y=go[i];
if(y==f) continue;
dp_(y,x);sz[x]+=sz[y];
dp[0][x]+=c[i]*sz[y]+dp[0][y];
if(dp[1][x]>dp[1][y]+c[i])
dp[1][x]=dp[1][y]+c[i],i1=y;
if(dp[2][x]<dp[2][y]+c[i])
dp[2][x]=dp[2][y]+c[i],i2=y;
}if(p[x]==2) as[2][x]=dp[2][x];
for(int i=d[x];i;i=nex[i]){
int y=go[i];if(y==f) continue;
as[0][x]+=as[0][y]+(c[i]*sz[y]+dp[0][y])*(sz[x]-sz[y]);
as[1][x]=min(as[1][y],as[1][x]);
as[2][x]=max(as[2][y],as[2][x]);
if(i1!=y)
as[1][x]=min(as[1][x],dp[1][x]+dp[1][y]+c[i]);
if(i2!=y)
as[2][x]=max(as[2][x],dp[2][x]+dp[2][y]+c[i]);
}
}int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1,x,y;i<n;i++)
cin>>x>>y,ad(x,y),ad(y,x);
dfs(1,0);
cin>>q;while(q--){
cin>>k;
for(int i=1;i<=k;i++)
cin>>a[i],b[++t]=a[i],p[a[i]]=2;
sort(a+1,a+k+1,cmp);
for(int i=1;i<k;i++){
int x=lca(a[i],a[i+1]);
if(!p[x]) p[x]=1,b[++t]=x;
}sort(b+1,b+t+1,cmp);
for(int i=1;i<t;i++){
int lc=lca(b[i],b[i+1]);
add(lc,b[i+1],dep[b[i+1]]-dep[lc]);
add(b[i+1],lc,dep[b[i+1]]-dep[lc]);
}int rt=lca(b[1],b[2]);dp_(rt,0);
cout<<as[0][rt]<<" "<<as[1][rt]<<" "<<as[2][rt]<<"\n";
for(int i=1;i<=t;i++){
p[b[i]]=sz[b[i]]=d[b[i]]=0;
dp[0][b[i]]=dp[1][b[i]]=dp[2][b[i]]=0;
as[0][b[i]]=dp[1][b[i]]=as[2][b[i]]=0;
}for(int i=1;i<=r;i++)
nex[i]=go[i]=c[i]=0;
r=t=0;
}return 0;
}

[HEOI2014]大工程 题解的更多相关文章

  1. [BZOJ3611][Heoi2014]大工程

    [BZOJ3611][Heoi2014]大工程 试题描述 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道.  我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上.  在 ...

  2. 【LG4103】[HEOI2014]大工程

    [LG4103][HEOI2014]大工程 题面 洛谷 题解 先建虚树,下面所有讨论均是在虚树上的. 对于第一问:直接统计所有树边对答案的贡献即可. 对于第\(2,3\)问:记\(f[x]\)表示在\ ...

  3. BZOJ2286 [Sdoi2011]消耗战 和 BZOJ3611 [Heoi2014]大工程

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6371  Solved: 2496[Submit][Statu ...

  4. 【BZOJ3611】[Heoi2014]大工程 欧拉序+ST表+单调栈

    [BZOJ3611][Heoi2014]大工程 Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道.  我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶 ...

  5. [Bzoj3611][Heoi2014]大工程(虚树)

    3611: [Heoi2014]大工程 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 2000  Solved: 837[Submit][Status ...

  6. bzoj 3611 [Heoi2014]大工程(虚树+DP)

    3611: [Heoi2014]大工程 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 408  Solved: 190[Submit][Status] ...

  7. 3611: [Heoi2014]大工程

    3611: [Heoi2014]大工程 链接 分析: 树形dp+虚树. 首先建立虚树,在虚树上dp. dp:sum[i]为i的子树中所有询问点之间的和.siz[i]为i的子树中有多少询问点,mn[i] ...

  8. P4103 [HEOI2014]大工程

    题目 P4103 [HEOI2014]大工程 化简题目:在树上选定\(k\)个点,求两两路径和,最大的一组路径,最小的一组路径 做法 关键点不多,建个虚树跑一边就好了 \(sum_i\)为\(i\)子 ...

  9. [BZOJ3611][Heoi2014]大工程(虚树上DP)

    3611: [Heoi2014]大工程 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 2464  Solved: 1104[Submit][Statu ...

  10. bzoj 3611: [Heoi2014]大工程 虚树

    题目: 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 ...

随机推荐

  1. 前端每日一知之让Chrome支持小于12px的文字

    脑图在线链接 本文内容依据[js每日一题]公众号精彩文章总结而来

  2. oracle查询某个sql语句客户端ip地址

    1. 背景 业务出现异常后,或者某个sql导致系统卡顿.需要问题后需要溯源,需要获取这个sql是在哪个客户端的IP发起的. 2. cs架构 客户端直接连接数据库,可以很方便查询,采用通过sql_id找 ...

  3. 【Amadeus原创】查找docker里程序源代码路径 上传本地文件

    1. 先找到container id ,诸如,我要进wikijs. id为3f6d2092f6ba docker ps 2. docker exec 进入container里面 docker exec ...

  4. Flutter之GetX之GetConnect

    Flutter之GetX之GetConnect GetConnect可以便捷的通过http或websockets进行前后台通信. 默认配置 能轻松的通过extend GetConnect就能使用GET ...

  5. 介绍 MSTest Runner - CLI, Visual Studio 等更多

    介绍 MSTest Runner - CLI, Visual Studio 等更多 https://devblogs.microsoft.com/dotnet/introducing-ms-test- ...

  6. ng-alain 创建页面

    https://ng-alain.com/cli/generate/zh https://ng-alain.com/docs/new-page/zh 默认情况下,创建模块 trade,创建在目录 sr ...

  7. Elm 和 Jetpack Compose 殊途同归及 MVVM 缺点分析

    Html.lazy · An Introduction to Elm 可能搞 vdom 的都会到 lazy renderer 这一步,react 可能也可以这么搞或者已经这么搞了我不知道,Elm 提到 ...

  8. function keyword is non-standard. Delete it.

    SC2112 – ShellCheck Wiki See this page on GitHub function keyword is non-standard. Delete it. Proble ...

  9. Eureka 缓存机制详细配置

    https://blog.csdn.net/qwe86314/article/details/94963865 上节为大家介绍了 Eureka 的工作原理,其中提到了 Eureka Server 内部 ...

  10. SSM或Spring Boot开发中,mapper包中的mapper.xml没有编译到targger中的解决办法

    SSM或Spring Boot开发中,mapper包中的mapper.xml没有编译到targger中的解决办法 在pom文件中加入如下配置: <resources> <!-- 编译 ...