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 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生不息.持 ...
随机推荐
- Codeforces 229D Towers
http://codeforces.com/problemset/problem/229/D 题意:有n(1<=n<=5,000)座塔排在一条直线上,从左到右每个塔的高度分别为hi(1&l ...
- Latch-up 閂鎖效應 & 靜電放電模式
* * Latch-up 閂鎖效應, 又稱寄生PNPN效應或可控矽整流器 ( SCR, Silicon Controlled Rectifier ) 效應. 在整體矽的CMOS 管下, 不同極性攙雜的 ...
- 图解SSL/TLS协议(转)
本周,CloudFlare宣布,开始提供Keyless服务,即你把网站放到它们的CDN上,不用提供自己的私钥,也能使用SSL加密链接. 我看了CloudFlare的说明(这里和这里),突然意识到这是绝 ...
- 域控制器安全策略在哪里 Windows server 2008
Start(开始)–Programs(程序)–Administrative Tools(管理工具)–Group Policy Management(策略管理器) 展开组策略管理器选择–Forest(林 ...
- Java数据结构: java.util.BitSet源码学习
接着上一篇Blog:一道面试题与Java位操作 和 BitSet 库的使用,分析下Java源码中BitSet类的源码. 位图(Bitmap),即位(Bit)的集合,是一种常用的数据结构,可用于记录大量 ...
- 杭电2059(dp)
龟兔赛跑 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- hdu4453-Looploop(伸展树)
题目有很多图,不好粘贴..... 题意:给出N个数和K1,K2的值,最开始指针指向第一个数,有6种操作 add x : 给前K2个数都增加x reverse : 翻转前K1个数 insert x : ...
- python部分排序算法(网友提供)
// 冒泡排序 def bubble(x,n): '''This function orders the original items x x is list,n is the length o ...
- [Git] --no-verify
Somtimes, the project might set the commit message guide line, if your commit doesn't meet the requi ...
- .NET中反射机制的使用与分析
.NET中反射机制的使用与分析 [日期:2008-06-30] 来源: 作者:志伟 .NET反射的定义:审查元数据并收集关于它的类型信息的能力. 元数据是一种二进制信息,用以对存储在公共语言 ...