题面

传送门

虚树

把跟询问有关的点拿出来建树,为了方便树\(DP\)

在\(LCA\)处要合并答案,那么把这些点的\(LCA\)也拿出来

做法:把点按\(dfs\)序排列,然后求出相邻两个点的\(LCA\),把这些点建一个虚树,维护一个栈就好了

Sol

虚树+树\(DP\)

# include <bits/stdc++.h>
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll; IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
} const int maxn(1e6 + 5);
const int inf(1e9); int n, first1[maxn], cnt, first2[maxn], id[maxn], p[maxn];
ll g[maxn], f[maxn], num[maxn], sum, mx, mn, tot;
int dfn[maxn], size[maxn], son[maxn], fa[maxn];
int s[maxn], top[maxn], idx, deep[maxn]; struct Edge{
int to, next;
} e2[maxn << 1], e1[maxn << 1]; IL void Add1(RG int u, RG int v){
e1[cnt] = (Edge){v, first1[u]}, first1[u] = cnt++;
} IL void Add2(RG int u, RG int v){
e2[cnt] = (Edge){v, first2[u]}, first2[u] = cnt++;
} IL void Dfs1(RG int u){
size[u] = 1;
for(RG int e = first1[u]; e != -1; e = e1[e].next){
RG int v = e1[e].to;
if(!size[v]){
deep[v] = deep[u] + 1;
Dfs1(v), size[u] += size[v], fa[v] = u;
if(size[v] > size[son[u]]) son[u] = v;
}
}
} IL void Dfs2(RG int u, RG int tp){
top[u] = tp, dfn[u] = ++idx;
if(son[u]) Dfs2(son[u], tp);
for(RG int e = first1[u]; e != -1; e = e1[e].next)
if(!dfn[e1[e].to]) Dfs2(e1[e].to, e1[e].to);
} IL int LCA(RG int u, RG int v){
while(top[u] ^ top[v])
deep[top[u]] > deep[top[v]] ? u = fa[top[u]] : v = fa[top[v]];
return deep[u] > deep[v] ? v : u;
} IL int Dis(RG int u, RG int v){
RG int lca = LCA(u, v);
return deep[u] + deep[v] - 2 * deep[lca];
} IL int Cmp(RG int u, RG int v){
return dfn[u] < dfn[v];
} IL void DP(RG int u){
g[u] = inf, f[u] = -inf;
if(num[u]) g[u] = f[u] = 0;
for(RG int e = first2[u]; e != -1; e = e2[e].next){
RG int v = e2[e].to, w = Dis(u, v);
DP(v), num[u] += num[v];
sum += (tot - num[v]) * num[v] * w;
mn = min(mn, g[u] + w + g[v]);
mx = max(mx, f[u] + w + f[v]);
g[u] = min(g[u], g[v] + w);
f[u] = max(f[u], f[v] + w);
}
} int main(){
n = Input();
for(RG int i = 1; i <= n; ++i) first1[i] = first2[i] = -1;
for(RG int i = 1; i < n; ++i){
RG int u = Input(), v = Input();
Add1(u, v), Add1(v, u);
}
Dfs1(1), Dfs2(1, 1);
for(RG int q = Input(); q; --q){
RG int k = Input(); cnt = 0, tot = k;
for(RG int i = 1; i <= k; ++i) p[i] = Input(), num[p[i]] = 1;
sort(p + 1, p + k + 1, Cmp);
for(RG int i = 1, t = k; i < t; ++i) p[++k] = LCA(p[i], p[i + 1]);
sort(p + 1, p + k + 1, Cmp), k = unique(p + 1, p + k + 1) - p - 1;
for(RG int i = 1; i <= k; ++i) first2[p[i]] = -1;
RG int t = 0;
for(RG int i = 1; i <= k; ++i){
while(t && dfn[p[i]] >= dfn[s[t]] + size[s[t]]) --t;
if(t) Add2(s[t], p[i]);
s[++t] = p[i];
}
mx = sum = 0, mn = inf;
DP(p[1]);
printf("%lld %lld %lld\n", sum, mn, mx);
for(RG int i = 1; i <= k; ++i) num[p[i]] = 0;
}
return 0;
}

虚树(Bzoj3611: [Heoi2014]大工程)的更多相关文章

  1. [BZOJ3611][Heoi2014]大工程

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

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

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

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

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

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

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

  5. BZOJ3611:[HEOI2014]大工程(树形DP,虚树)

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

  6. BZOJ3611 [Heoi2014]大工程 【虚树】

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

  7. [BZOJ3611] [Heoi2014]大工程(DP + 虚树)

    传送门 $dp[i][0]$表示节点i到子树中的所有点的距离之和 $dp[i][1]$表示节点i到子树中最近距离的点的距离 $dp[i][2]$表示节点i到子树中最远距离的点的距离 建好虚树后dp即可 ...

  8. BZOJ3611 HEOI2014大工程

    先建虚树,然后统计答案. 对于这个两点间最大值和最小值的操作我参考了hzwer的代码. 建虚树时注意判自环 By:大奕哥 #include<bits/stdc++.h> using nam ...

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

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

随机推荐

  1. Unicode字符串索引

    一.目标 在通讯录中,我们有很多联系人,需要把这些联系人进行索引.对于每一个索引项对应的若干字符串,需要对这些字符串进行排序. 需要解决两个问题: 如何确定某个汉字应该被哪个字符索引? 某个索引项对应 ...

  2. mybatis一级缓存与二级缓存的原理

    1.mybatis中的缓存是在mybatis框架中的Executor中来实现的,我们来看一下Executor的继承图 2.通过以上类图我们可以发现Executor接口下有两大实现类BaseExecut ...

  3. IDEA自动生成TestNG的testng.xml的插件

    某地方见到的,自己实际操作一遍,记录一下.方便以后查询. 下载Create TestNG XML 插件,重启IDEA即可. 重启idea,新建Maven项目. pom.xml增加依赖 <depe ...

  4. 编译原理(六)自底向上分析之LR分析法

    自底向上分析之LR分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本概念 1. LR分析:从左到右扫描(L)自底向上进行规约(R),是规范规约,也即最右推导(规范推导) ...

  5. mysql导入大批量数据出现MySQL server has gone away的解决方法

    因工作需要,需要导入一个200M左右的sql到user库 执行命令 mysql> use user Database changed mysql> source /tmp/user.sql ...

  6. 1. C++11保证稳定性与兼容性

    1.1 __func__预定义标识符 在c99中,__func__基本功能是返回所在函数的名字,c++11中允许使用在类或结构体中. #include <iostream> using n ...

  7. VS2010一调试就卡死的问题解决方案 (转)

    前几天我的vs2010突然不能调试了.后来找了很多的解决方案都不能解决问题. 1. 删除所有的bin, debug 2. 重建工程. 3. 重新安装Silverlight的开发包. 还是不行. 最后是 ...

  8. OpenERP __sql_constrants doesn't work.

    可能的原因有两个,一个是你没有更新模块列表,第二个可能是你原有的列已经有重复的数据.(unique限制为例.)

  9. Memcahe安装与配置

    1.先启动Memcahe服务 (1)通过Memcahe文件夹下的memcahe.exe程序启动 (2)将Memcahe加到Windows服务中去 为了方便使用,大多数情况下,是使用第二种方式,来启动M ...

  10. Cloudera Manager安装之利用parcels方式安装单节点集群(包含最新稳定版本或指定版本的安装)(添加服务)(CentOS6.5)(四)

    不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑          ...