[BZOJ3611][Heoi2014]大工程
[BZOJ3611][Heoi2014]大工程
试题描述
输入
第一行 n 表示点数。
输出
输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。
输入示例
输出示例
数据规模及约定
n<=1000000
q<=50000并且保证所有k之和<=2*n
题解
建出虚树后恶心 dp。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <algorithm>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 1000010
#define maxm 2000010
#define maxlog 20
#define oo 2147483647
#define LL long long
int n, m, head[maxn], next[maxm], to[maxm]; void AddEdge(int a, int b) {
to[++m] = b; next[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; next[m] = head[a]; head[a] = m;
return ;
} int ord[maxn], clo, dep[maxn], fa[maxlog][maxn];
void build(int u) {
ord[u] = ++clo;
for(int i = 1; i < maxlog; i++) fa[i][u] = fa[i-1][fa[i-1][u]];
for(int e = head[u]; e; e = next[e]) if(to[e] != fa[0][u]) {
fa[0][to[e]] = u;
dep[to[e]] = dep[u] + 1;
build(to[e]);
}
return ;
}
int lca(int a, int b) {
if(dep[a] < dep[b]) swap(a, b);
for(int i = maxlog - 1; i >= 0; i--) if(dep[a] - (1 << i) >= dep[b]) a = fa[i][a];
for(int i = maxlog - 1; i >= 0; i--) if(fa[i][a] != fa[i][b]) a = fa[i][a], b = fa[i][b];
return a == b ? a : fa[0][b];
} bool cmp(int a, int b) { return ord[a] < ord[b]; }
int ps[maxn], cp, psi[maxn], cpi, vis[maxn], siz[maxn], mn[maxn], mx[maxn], mn2[maxn], mx2[maxn];
bool flg[maxn];
LL f[maxn], sum[maxn];
int m2, h2[maxn], n2[maxm], t2[maxm], d2[maxm];
void Add2(int a, int b, int c) {
// printf("add2: %d %d %d\n", a, b, c);
t2[++m2] = b; d2[m2] = c; n2[m2] = h2[a]; h2[a] = m2;
swap(a, b);
t2[++m2] = b; d2[m2] = c; n2[m2] = h2[a]; h2[a] = m2;
return ;
}
void dp(int u, int pa) {
sum[u] = f[u] = siz[u] = 0;
mn[u] = oo; mx[u] = mx2[u] = 0;
if(flg[u]) mn2[u] = 0; else mn2[u] = oo;
for(int e = h2[u]; e; e = n2[e]) if(t2[e] != pa) {
dp(t2[e], u);
LL tmp = sum[t2[e]] + (LL)siz[t2[e]] * d2[e];
f[u] += sum[u] * siz[t2[e]] + tmp * siz[u] + f[t2[e]];
// printf("t2[e]: %d %lld %lld %d\n", t2[e], sum[u], tmp, siz[u]);
sum[u] += tmp;
siz[u] += siz[t2[e]];
mn[u] = min(mn[u], mn[t2[e]]);
if(mn2[t2[e]] < oo) {
if(mn2[u] < oo) mn[u] = min(mn[u], mn2[u] + mn2[t2[e]] + d2[e]);
mn2[u] = min(mn2[u], mn2[t2[e]] + d2[e]);
}
mx[u] = max(mx[u], mx[t2[e]]);
mx[u] = max(mx[u], mx2[u] + mx2[t2[e]] + d2[e]);
mx2[u] = max(mx2[u], mx2[t2[e]] + d2[e]);
}
f[u] += sum[u] * flg[u];
siz[u] += flg[u];
// printf("u: %d %d %lld %lld %d\n", u, pa, f[u], sum[u], siz[u]);
h2[u] = flg[u] = 0;
return ;
} int main() {
n = read();
for(int i = 1; i < n; i++) {
int a = read(), b = read();
AddEdge(a, b);
}
build(1);
// for(int i = 1; i <= n; i++) printf("%d%c", ord[i], i < n ? ' ' : '\n'); int q = read();
while(q--) {
cpi = read(); cp = 0;
for(int i = 1; i <= cpi; i++) {
psi[i] = read();
vis[psi[i]] = q + 1;
ps[++cp] = psi[i];
flg[ps[cp]] = 1;
}
sort(psi + 1, psi + cpi + 1, cmp);
int rt, dr = oo;
for(int i = 1; i < cpi; i++) {
int c = lca(psi[i], psi[i+1]);
if(dep[c] < dr) dr = dep[c], rt = c;
if(vis[c] != q + 1) vis[c] = q + 1, ps[++cp] = c;
}
sort(ps + 1, ps + cp + 1, cmp);
m2 = 0;
// for(int i = 1; i <= cp; i++) printf("%d%c", ps[i], i < cp ? ' ' : '\n');
for(int i = 1; i < cp; i++) {
int a = ps[i], b = ps[i+1], c = lca(a, b);
Add2(b, c, dep[b] - dep[c]);
}
dp(rt, 0);
printf("%lld %d %d\n", f[rt], mn[rt], mx[rt]);
} return 0;
}
[BZOJ3611][Heoi2014]大工程的更多相关文章
- [BZOJ3611][Heoi2014]大工程(虚树上DP)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 2464 Solved: 1104[Submit][Statu ...
- BZOJ2286 [Sdoi2011]消耗战 和 BZOJ3611 [Heoi2014]大工程
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6371 Solved: 2496[Submit][Statu ...
- [Bzoj3611][Heoi2014]大工程(虚树)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 2000 Solved: 837[Submit][Status ...
- BZOJ3611:[HEOI2014]大工程(树形DP,虚树)
Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通 ...
- BZOJ3611 [Heoi2014]大工程 【虚树】
题目 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a ...
- BZOJ3611 HEOI2014大工程
先建虚树,然后统计答案. 对于这个两点间最大值和最小值的操作我参考了hzwer的代码. 建虚树时注意判自环 By:大奕哥 #include<bits/stdc++.h> using nam ...
- 虚树(Bzoj3611: [Heoi2014]大工程)
题面 传送门 虚树 把跟询问有关的点拿出来建树,为了方便树\(DP\) 在\(LCA\)处要合并答案,那么把这些点的\(LCA\)也拿出来 做法:把点按\(dfs\)序排列,然后求出相邻两个点的\(L ...
- [BZOJ3611] [Heoi2014]大工程(DP + 虚树)
传送门 $dp[i][0]$表示节点i到子树中的所有点的距离之和 $dp[i][1]$表示节点i到子树中最近距离的点的距离 $dp[i][2]$表示节点i到子树中最远距离的点的距离 建好虚树后dp即可 ...
- 【BZOJ3611】[Heoi2014]大工程 欧拉序+ST表+单调栈
[BZOJ3611][Heoi2014]大工程 Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶 ...
随机推荐
- putty配色方案
最近用腻了putty默认的配色方案,所以打算换一下配色. 使用的是修改注册表的方法. 1.打开注册表:运行——>regedit 2.找到对应的注册表文件,并导出:注册表地址 HKEY_CURRE ...
- FPS
游戏的FPS跟什么有关 http://zhidao.baidu.com/link?url=jZJoN_-MTC9fWCBSBaL5vezBp13MRSv8PdCcQMbwX5tiFGzxNEHe7UB ...
- xheditor编辑器的使用
xheditor编辑器的使用 一个博客.cms网站都一定会用到一个html编辑器,刚好xmfdsh在做网站时候需要用到这类编辑器,在对比了之后,发现其实差不了多少,刚好一个不错的friend在用xhe ...
- adobe photoshop cc 2014 安装失败 解决办法之一
首先安装失败会有提示 首先贴下错误信息 Exit Code: 34 Please see specific errors below for troubleshooting. For example, ...
- yii2 登录、退出、自动登录
自动登录的原理很简单.主要就是利用cookie来实现的在第一次登录的时候,如果登录成功并且选中了下次自动登录,那么就会把用户的认证信息保存到cookie中,cookie的有效期为1年或者几个月. 在下 ...
- gradle 默认属性
Properties(未翻译) Property Description allprojects 包含该项目及其子项目的属性 ant The AntBuilder for this project. ...
- kafka环境搭建及librdkafka测试
kafka环境搭建及librdkafka测试 (2016-04-05 10:18:25) 一.kafka环境搭建(转自http://kafka.apache.org/documentation.h ...
- mysql规范
1.命名规范 (1)库名.表名.(按现在的规范类似; PromoHayaoRecord),数据库名使用小写,字段名必须使用小写字母,并采用下划线分割.(2)库名.表名.字段名禁止超过32个字符.(3) ...
- Spring与Quartz的整合实现定时任务调度(转)
源:http://kevin19900306.iteye.com/blog/1397744 最近在研究Spring中的定时任务功能,最好的办法当然是使用Quartz来实现.对于一个新手来说,花了我不少 ...
- HTTP状态301、404、200、304分别表示什么意思
301 (永久移动)请求的网页已永久移动到新位置.服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置.您应使用此代码告诉 Googlebot 某个网页或网站已永久移动 ...