BZOJ 3572 世界树(虚树)
http://www.lydsy.com/JudgeOnline/problem.php?id=3572
思路:建立虚树,然后可以发现,每条边不是同归属于一端,那就是切开,一半给上面,一半给下面。
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#define N 300005
int tot,go[N*],next[N*],first[N],sz,deep[N],tmp[N],tree[N];
int son[N],dfn[N],fa[N][],bin[],ask[N],In[N],st[N],n,m,ans[N];
int father[N],val[N];
std::pair<int,int>near[N];
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
}
void add(int x,int y){
insert(x,y);insert(y,x);
}
void dfs(int x){
son[x]=;
dfn[x]=++sz;
for (int i=;i<=;i++)
fa[x][i]=fa[fa[x][i-]][i-];
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa[x][]) continue;
deep[pur]=deep[x]+;
fa[pur][]=x;
dfs(pur);
son[x]+=son[pur];
}
}
int find(int x,int dep){
for (int i=;i>=;i--)
if (deep[fa[x][i]]>=dep) x=fa[x][i];
return x;
}
int lca(int x,int y){
if (deep[x]<deep[y]) std::swap(x,y);
int t=deep[x]-deep[y];
for (int i=;i<=;i++)
if (t&bin[i])
x=fa[x][i];
if (x==y) return x;
for (int i=;i>=;i--)
if (fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][];
}
bool cmp(int a,int b){
return dfn[a]<dfn[b];
}
void solve(){
m=read();
for (int i=;i<=m;i++){
ask[i]=read(),tmp[i]=tree[i]=ask[i];
near[ask[i]]=std::make_pair(,ask[i]);
ans[ask[i]]=;
}
std::sort(ask+,ask++m,cmp);
int top=,all=m;
for (int i=;i<=m;i++){
int p=ask[i];
if (!top) father[p]=,st[++top]=p;
else{
int x=lca(st[top],p);
father[p]=x;
while (top&&deep[st[top]]>deep[x]){
if (deep[st[top-]]<=deep[x]){
father[st[top]]=x;
}
top--;
}
if (st[top]!=x){
father[x]=st[top];tree[++all]=x;
st[++top]=x;near[x]=std::make_pair(<<,);
}
st[++top]=p;
}
}
std::sort(tree+,tree++all,cmp);
for (int i=;i<=all;i++){
int p=tree[i],f=father[p];
val[p]=son[p];
if (i>) In[p]=deep[p]-deep[f];
}
for (int i=all;i>;i--){
int p=tree[i],f=father[p];
near[f]=std::min(near[f],std::make_pair(near[p].first+In[p],near[p].second));
}
for (int i=;i<=all;i++){
int p=tree[i],f=father[p];
near[p]=std::min(near[p],std::make_pair(near[f].first+In[p],near[f].second));
}
for (int i=;i<=all;i++){
int p=tree[i],f=father[p],sum=son[find(p,deep[f]+)]-son[p];
if (f==) ans[near[p].second]+=n-son[p];
else{
val[f]-=sum+son[p];
if (near[p].second==near[f].second) ans[near[p].second]+=sum;
else{
int dis=(deep[p]-deep[f]-near[p].first+near[f].first)/;
if (dis+near[p].first==near[f].first+deep[p]-deep[f]-dis&&near[f].second<near[p].second) dis--;
int x=find(p,deep[p]-dis);
ans[near[p].second]+=son[x]-son[p];
ans[near[f].second]+=sum+son[p]-son[x];
}
}
}
for (int i=;i<=all;i++){
ans[near[tree[i]].second]+=val[tree[i]];
}
for (int i=;i<=m;i++)
printf("%d ",ans[tmp[i]]);
puts("");
}
int main(){
n=read();
bin[]=;
for (int i=;i<=;i++) bin[i]=bin[i-]*;
for (int i=;i<n;i++){
int x=read(),y=read();
add(x,y);
}
dfs();
int T=read();
while (T--) solve();
}
BZOJ 3572 世界树(虚树)的更多相关文章
- bzoj 3572世界树 虚树+dp
题目大意: 给一棵树,每次给出一些关键点,对于树上每个点,被离它最近的关键点(距离相同被标号最小的)控制 求每个关键点控制多少个点 分析: 虚树+dp dp过程如下: 第一次dp,递归求出每个点子树中 ...
- bzoj 3572 [Hnoi2014]世界树——虚树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3572 关于虚树:https://www.cnblogs.com/zzqsblog/p/556 ...
- bzoj 3572: [Hnoi2014]世界树 虚树 && AC500
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 520 Solved: 300[Submit][Status] ...
- BZOJ 3572: [Hnoi2014]世界树 虚树 树形dp
https://www.lydsy.com/JudgeOnline/problem.php?id=3572 http://hzwer.com/6804.html 写的时候参考了hzwer的代码,不会写 ...
- bzoj 3572: [Hnoi2014]世界树 虚树
题目: Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生 ...
- BZOJ 3572 [HNOI2014]世界树 (虚树+DP)
题面:BZOJ传送门 洛谷传送门 题目大意:略 细节贼多的虚树$DP$ 先考虑只有一次询问的情况 一个节点$x$可能被它子树内的一个到x距离最小的特殊点管辖,还可能被管辖fa[x]的特殊点管辖 跑两次 ...
- BZOJ 3572: [Hnoi2014]世界树 [虚树 DP 倍增]
传送门 题意: 一棵树,多次询问,给出$m$个点,求有几个点到给定点最近 写了一晚上... 当然要建虚树了,但是怎么$DP$啊 大爷题解传送门 我们先求出到虚树上某个点最近的关键点 然后枚举所有的边$ ...
- 【BZOJ】3572: [Hnoi2014]世界树 虚树+倍增
[题意]给定n个点的树,m次询问,每次给定ki个特殊点,一个点会被最近的特殊点控制,询问每个特殊点控制多少点.n,m,Σki<=300000. [算法]虚树+倍增 [题解]★参考:thy_asd ...
- BZOJ 3572 世界树
Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生不息.持 ...
随机推荐
- 使用StreamReader与StreamWriter进行文本文件读写
namespace filetest { class FileUtil { public static void WriteFile(string file) { using (FileStream ...
- fuse 虚拟文件系统 的 安装与使用
FUSE 是个好东西, 可以用在特殊的领域里面来实现自己的虚拟文件系统. FUSE的下载与安装 : 从fuse官网下载最新安装包:http://sourceforge.net/projects/fus ...
- 为什么ASCII是7位(导致各家编码的128~256字符都不同,给我带来很多困惑)——在标准ASCII中,其最高位(b7)用作奇偶校验位,附ASCII每个控制符的中文解释
ASCII编码 ASCII是基于拉丁字母的一套电脑编码系统.它主要用于显示现代英语和其他西欧语言.它是现今最通用的单字节编码系统,并等同于国际标准ISO/IEC 646. 请注意,ASCII是Amer ...
- rsyslog input 不支持变量
input(type="imfile" File="/usr/local/apache-tomcat-7.0.55_8082/logs/localhost_access_ ...
- Unable to resolve target 'android-14' 解决办法
学习安卓的时候用Eclipse导入工程之后出现Unable to resolve target 'android-14' 这样的问题,代码确定没有问题,因为是从网上教程下载的示例代码,上网搜索了一下, ...
- uva 11210 Chinese Mahjong(暴力搜索)
Chinese Mahjong Mahjong () is a game of Chinese origin usually played by four persons with tiles res ...
- 【问题备注】VS2012不能输入代码,文字…
第一次遇到,非常奇怪,一个项目,VS2012能正常打开,但是不能输入代码. 对比分析发现,其他项目能正常work.在于一个问题就是,VS2012 右下角有个INS一直在转一直analyzing,而正常 ...
- Python3.5入门学习记录-条件控制
Python的条件控制同C#一样,都是通过一条或多条语句的执行结果(True OR False)来决定执行的代码块. if 语句 Python中if语句的一般形式如下所示: if condition_ ...
- 写一个Windows上的守护进程(7)捕获异常并生成dump
写一个Windows上的守护进程(7)捕获异常并生成dump 谁都不能保证自己的代码不出bug.一旦出了bug,最好是崩溃掉,这样很快就能被发现,若是不崩溃,只是业务处理错了,就麻烦了,可能很长时间之 ...
- zongjie
$msg = $_GET['msg'];$startDate = $_POST['startDate'];$endDate = $_POST['endDate'];$quickdate = $_POS ...