题面

题解

虚树好题(只是细节太多)

构出虚树后,一定要仔细梳理关键点之间的点是上面属于父亲,下面属于儿子。

然后二分出所有的点的所属就可以了

代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define clear(x, y) memset(x, y, sizeof(x)) inline int read()
{
int data = 0, w = 1; char ch = getchar();
while(ch != '-' && (!isdigit(ch))) ch = getchar();
if(ch == '-') w = -1, ch = getchar();
while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
return data * w;
} const int maxn(300010);
struct edge { int next, to, dis; } e[maxn << 1];
int head[maxn], e_num, n, q, f[21][maxn], dep[maxn], belong[maxn];
int size[maxn], dfn[maxn], cnt, stk[maxn], top, sur[maxn], dis[maxn]; inline void add_edge(int from, int to, int dis = 1)
{
e[++e_num] = (edge) {head[from], to, dis};
head[from] = e_num;
} void dfs(int x)
{
dep[x] = dep[f[0][x]] + 1; size[x] = 1;
for(RG int i = 1; i <= 20; i++)
f[i][x] = f[i - 1][f[i - 1][x]];
dfn[x] = ++cnt;
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(to == f[0][x]) continue;
f[0][to] = x; dfs(to); size[x] += size[to];
}
} int LCA(int a, int b)
{
if(dep[a] < dep[b]) std::swap(a, b);
for(RG int i = 20; ~i; i--) if(dep[f[i][a]] >= dep[b]) a = f[i][a];
if(a == b) return a;
for(RG int i = 20; ~i; i--) if(f[i][a] != f[i][b]) a = f[i][a], b = f[i][b];
return f[0][a];
} int jump(int x, int k)
{
if(dep[x] < k) return x;
for(RG int i = 20; ~i; i--) if(dep[f[i][x]] >= k) x = f[i][x];
return x;
} struct node { int x, id; } p[maxn];
inline bool cmpx(const node &lhs, const node &rhs)
{ return dfn[lhs.x] < dfn[rhs.x]; }
inline bool cmpid(const node &lhs, const node &rhs) { return lhs.id < rhs.id; }
int k, vis[maxn], ans[maxn], t[maxn], tot;
void build()
{
std::sort(p + 1, p + k + 1, cmpx);
stk[top = 1] = 1;
for(RG int i = 1; i <= k; i++)
{
int x = p[i].x; if(x == 1) continue;
int lca = LCA(stk[top], x);
while(top > 1 && dep[stk[top - 1]] > dep[lca])
{
int dis = dep[stk[top]] - dep[stk[top - 1]];
add_edge(stk[top], stk[top - 1], dis);
add_edge(stk[top - 1], stk[top], dis);
--top;
} if(dep[lca] < dep[stk[top]])
{
int dis = dep[stk[top]] - dep[lca];
add_edge(stk[top], lca, dis);
add_edge(lca, stk[top], dis);
--top;
} if(dep[lca] > dep[stk[top]]) stk[++top] = lca;
stk[++top] = x;
} while(top > 1)
{
int dis = dep[stk[top]] - dep[stk[top - 1]];
add_edge(stk[top], stk[top - 1], dis);
add_edge(stk[top - 1], stk[top], dis);
--top;
}
} void dfs1(int x, int fa)
{
sur[x] = size[x]; t[++tot] = x;
if(vis[x]) dis[x] = 0, belong[x] = x;
else dis[x] = 1e9;
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(to == fa) continue;
dfs1(to, x);
if(dis[x] > dis[to] + e[i].dis ||
(dis[x] == dis[to] + e[i].dis && belong[x] > belong[to]))
dis[x] = dis[to] + e[i].dis, belong[x] = belong[to];
}
} void dfs2(int x, int fa)
{
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(to == fa) continue;
if(dis[to] > dis[x] + e[i].dis ||
(dis[to] == dis[x] + e[i].dis && belong[to] > belong[x]))
dis[to] = dis[x] + e[i].dis, belong[to] = belong[x];
dfs2(to, x);
if(belong[to] == belong[x]) sur[x] -= size[to];
else
{
int d = dis[to] + dis[x] + dep[to] - dep[x] - 1, k = d / 2 - dis[to];
int t = jump(to, dep[to] - k);
if((d & 1) && belong[x] > belong[to] && k >= 0) t = f[0][t];
sur[to] += size[t] - size[to], sur[x] -= size[t];
}
ans[belong[to]] += sur[to];
}
if(x == 1) ans[belong[x]] += sur[x];
} int main()
{
#ifndef ONLINE_JUDGE
file(cpp);
#endif
n = read();
for(RG int i = 1, a, b; i < n; i++)
a = read(), b = read(), add_edge(a, b), add_edge(b, a);
dfs(1); q = read(); clear(head, 0); e_num = 0;
while(q--)
{
k = read();
for(RG int i = 1; i <= k; i++)
vis[(p[i] = (node) {read(), i}).x] = 1;
build(); dfs1(1, 0); dfs2(1, 0);
std::sort(p + 1, p + k + 1, cmpid);
for(RG int i = 1; i <= k; i++) printf("%d ", ans[p[i].x]);
puts(""); e_num = 0;
for(RG int i = 1; i <= tot; i++)
vis[t[i]] = head[t[i]] = ans[t[i]]
= sur[t[i]] = belong[t[i]] = dis[t[i]] = 0;
tot = 0;
}
return 0;
}

【HNOI2014】世界树的更多相关文章

  1. [BZOJ3572][Hnoi2014]世界树

    [BZOJ3572][Hnoi2014]世界树 试题描述 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条 ...

  2. BZOJ 3572: [Hnoi2014]世界树

    BZOJ 3572: [Hnoi2014]世界树 标签(空格分隔): OI-BZOJ OI-虚数 OI-树形dp OI-倍增 Time Limit: 20 Sec Memory Limit: 512 ...

  3. bzoj 3572: [Hnoi2014]世界树 虚树 && AC500

    3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 520  Solved: 300[Submit][Status] ...

  4. bzoj 3572 [Hnoi2014]世界树(虚树+DP)

    3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 645  Solved: 362[Submit][Status] ...

  5. 【BZOJ3572】[Hnoi2014]世界树 虚树

    [BZOJ3572][Hnoi2014]世界树 Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森 ...

  6. bzoj3572[Hnoi2014] 世界树 虚树+dp+倍增

    [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1921  Solved: 1019[Submit][Status][Dis ...

  7. <虚树+树型DP> HNOI2014世界树

    <虚树+树型DP> HNOI2014世界树 #include <iostream> #include <cstdio> #include <cstring&g ...

  8. [题解] [HNOI2014] 世界树

    题面 [HNOI2014]世界树 题解 从数据范围很容易看出是个虚树DP(可惜看出来了也还是不会做) 虚树大家应该都会, 不会的话自己去搜吧, 我懒得讲了, 我们在这里只需要考虑如何DP即可 首先我们 ...

  9. [HNOI2014]世界树

    题目描述 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生不息.持续运转的根本基 ...

  10. BZOJ3572:[HNOI2014]世界树——题解

    +++++++++++++++++++++++++++++++++++++++++++ +本文作者:luyouqi233. + +欢迎访问我的博客:http://www.cnblogs.com/luy ...

随机推荐

  1. jq局部打印插件jQuery.print.js(兼容IE8)

    /* @license * jQuery.print, version 1.5.1 * (c) Sathvik Ponangi, Doers' Guild * Licence: CC-By (http ...

  2. Java基础知识强化之集合框架笔记77:ConcurrentHashMap之 ConcurrentHashMap的基本操作

    1. ConcurrentHashMap的初始化: 下面我们来结合源代码来具体分析一下ConcurrentHashMap的实现,先看下初始化方法: public ConcurrentHashMap(i ...

  3. 使用泛型和内部静态类实现栈(FILO,先进后出)

    package tuple; /** * 泛型实现的栈,FILO * @author Youjie * * @param <T> */ public class LinkedStack&l ...

  4. Java并发案例01---多线程之死锁

    多线程之死锁案例一 package example; /** * 模拟死锁 * @author maple * */ public class DeadLock { public int flag = ...

  5. Hadoop学习之路(十九)MapReduce框架排序

    流量统计项目案例 样本示例 需求 1. 统计每一个用户(手机号)所耗费的总上行流量.总下行流量,总流量 2. 得出上题结果的基础之上再加一个需求:将统计结果按照总流量倒序排序 3. 将流量汇总统计结果 ...

  6. 图论——最短路径 Dijkstra算法、Floyd算法

    1.弗洛伊德算法(Floyd) 弗洛伊算法核心就是三重循环,M [ j ] [ k ] 表示从 j 到 k 的路径,而 i 表示当前 j 到 k 可以借助的点:红色部分表示,如果 j 到 i ,i 到 ...

  7. 贪心——HDU-5969 最大的位或

    HDU-5969:http://acm.hdu.edu.cn/showproblem.php?pid=5969 一开始也是分了类,觉得要两种情况,l 与 r 位数相同与不同的情况,仔细想一下,可以一起 ...

  8. 1、RabbitMQ入门

    RabbitMQ 可以参考官网进行学习! 开发语言:Erlang – 面向并发的编程语言. AMQP:是消息队列的一个协议. mysql 是 java 写的吗?不是 那么 java 能不能访问?可以, ...

  9. [Luogu2622]关灯问题$||$(状压$DP$)

    #\(\color{red}{\mathcal{Description}}\) \(Link\) 现有\(n\)盏灯,以及\(m\)个按钮.每个按钮可以同时控制这\(n\)盏灯--按下了第i个按钮,对 ...

  10. Mac 下 SVN 的使用

    在Windows环境中,我们一般使用TortoiseSVN来搭建svn环境.在Mac环境下,由于Mac自带了svn的服务器端和客户端功能,所以我们可以在不装任何第三方软件的前提下使用svn功能,不过还 ...