#虚树,树形dp#洛谷 3233 [HNOI2014]世界树
分析
考虑建一棵虚树,倍增找到虚树上相邻两个点的中间点统计答案
记录每个虚树点最近的距离以及编号最小的点,主要是细节问题
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=300011; struct node{int y,next;}e[N<<1],E[N];
int dep[N],siz[N],v[N],dfn[N],tot,f[N][19],a[N],lg[N],stac[N];
int low[N],dp[N],W[N],b[N],n,m,et=1,Et,ans[N],as[N],hs[N],mm;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline void dfs(int x,int fa){
dep[x]=dep[fa]+1,siz[x]=1,dfn[x]=++tot,f[x][0]=fa;
for (rr int i=0;f[x][i];++i) f[x][i+1]=f[f[x][i]][i];
for (rr int i=as[x];i;i=e[i].next)
if (e[i].y!=fa) dfs(e[i].y,x),siz[x]+=siz[e[i].y];
}
inline signed lca(int x,int y){
if (dep[x]<dep[y]) x^=y,y^=x,x^=y;
for (rr int i=lg[dep[x]];~i;--i)
if (dep[f[x][i]]>=dep[y]) x=f[x][i];
if (x==y) return x;
for (rr int i=lg[dep[x]];~i;--i)
if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
inline void add(int x,int y){E[++Et]=(node){y,hs[x]},W[Et]=dep[y]-dep[x],hs[x]=Et;}
inline void Insert(int x){
if (!tot) {stac[++tot]=x; return;}
rr int Lca=lca(x,stac[tot]);
while (tot>1&&dep[Lca]<dep[stac[tot-1]]) add(stac[tot-1],stac[tot]),--tot;
if (dep[Lca]<dep[stac[tot]]) add(Lca,stac[tot]),--tot;
if (stac[tot]!=Lca) stac[++tot]=Lca; stac[++tot]=x;
}
inline void dfs1(int x,int fa){
dp[x]=1e7;
for (rr int i=hs[x];i;i=E[i].next)
if (E[i].y!=fa){
dfs1(E[i].y,x);
if (dp[E[i].y]+W[i]<dp[x]) dp[x]=dp[E[i].y]+W[i],low[x]=low[E[i].y];
else if (dp[E[i].y]+W[i]==dp[x]&&low[x]>low[E[i].y]) low[x]=low[E[i].y];
}
if (v[x]) dp[x]=0,low[x]=x;
}
inline void answ(int x,int fa){
rr int x1=x,x2=x;
for (rr int i=lg[dep[x1]];~i;--i)
if (dep[f[x1][i]]>dep[fa]) x1=f[x1][i];
ans[low[fa]]-=siz[x1];//先把可能影响的点删除
for (rr int i=lg[dep[x2]];~i;--i){
rr int Bot=dep[x]-dep[f[x2][i]]+dp[x],Top=dep[f[x2][i]]-dep[fa]+dp[fa];
if (dep[f[x2][i]]>dep[fa]&&(Bot<Top||(Bot==Top&&low[x]<low[fa]))) x2=f[x2][i];
}
ans[low[fa]]+=siz[x1]-siz[x2],ans[low[x]]+=siz[x2]-siz[x];//用中间点分开统计贡献
}
inline void dfs2(int x,int fa){
for (rr int i=hs[x];i;i=E[i].next)
if (E[i].y!=fa){
if (dp[x]+W[i]<dp[E[i].y]) dp[E[i].y]=dp[x]+W[i],low[E[i].y]=low[x];
else if (dp[x]+W[i]==dp[E[i].y]&&low[E[i].y]>low[x]) low[E[i].y]=low[x];
answ(E[i].y,x),dfs2(E[i].y,x);
}
ans[low[x]]+=siz[x],hs[x]=0;//补回未加入的点
}
signed main(){
n=iut(),lg[0]=-1;
for (rr int i=1;i<=n;++i) lg[i]=lg[i>>1]+1;
for (rr int i=1;i<n;++i){
rr int x=iut(),y=iut();
e[++et]=(node){y,as[x]},as[x]=et;
e[++et]=(node){x,as[y]},as[y]=et;
}
dfs(1,0);
for (rr int Q=iut();Q;--Q){
mm=m=iut(),tot=Et=0,a[++m]=1;
for (rr int i=1;i<m;++i) v[b[i]=a[i]=iut()]=1;
sort(a+1,a+1+m,cmp),m=unique(a+1,a+1+m)-a-1;
for (rr int i=1;i<=m;++i) Insert(a[i]);
for (;tot>1;--tot) add(stac[tot-1],stac[tot]);
dfs1(1,0),dfs2(1,0);
for (rr int i=1;i<=mm;++i) if (b[i])
print(ans[b[i]]),putchar(i==mm?10:32),ans[b[i]]=0;
for (rr int i=1;i<=m;++i) v[a[i]]=0;
}
return 0;
}
#虚树,树形dp#洛谷 3233 [HNOI2014]世界树的更多相关文章
- 【BZOJ-3572】世界树 虚树 + 树形DP
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1084 Solved: 611[Submit][Status ...
- 【BZOJ-2286】消耗战 虚树 + 树形DP
2286: [Sdoi2011消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2120 Solved: 752[Submit][Status] ...
- bzoj 2286(虚树+树形dp) 虚树模板
树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5002 Sol ...
- BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca
BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...
- 洛谷 P3233 [HNOI2014]世界树(虚树+dp)
题面 luogu 题解 数据范围已经告诉我们是虚树了,考虑如何在虚树上面\(dp\) 以下摘自hzwer博客: 构建虚树以后两遍dp处理出虚树上每个点最近的议事处 然后枚举虚树上每一条边,考虑其对两端 ...
- 2018.09.25 bzoj3572: [Hnoi2014]世界树(虚树+树形dp)
传送门 虚树入门题? 好难啊. 在学习别人的写法之后终于过了. 这道题dp方程很好想. 主要是不好写. 简要说说思路吧. 显然最优值只能够从子树和父亲转移过来. 于是我们先dfs一遍用儿子更新父亲,然 ...
- BZOJ5341[Ctsc2018]暴力写挂——边分治+虚树+树形DP
题目链接: CSTC2018暴力写挂 题目大意:给出n个点结构不同的两棵树,边有边权(有负权边及0边),要求找到一个点对(a,b)满足dep(a)+dep(b)-dep(lca)-dep'(lca)最 ...
- [WC2018]通道——边分治+虚树+树形DP
题目链接: [WC2018]通道 题目大意:给出三棵n个节点结构不同的树,边有边权,要求找出一个点对(a,b)使三棵树上这两点的路径权值和最大,一条路径权值为路径上所有边的边权和. 我们按照部分分逐个 ...
- ●洛谷P3233 [HNOI2014]世界树
题链: https://www.luogu.org/problemnew/show/P3233题解: 虚树,dp,倍增. 首先对于每个询问,要把虚树建出来,这一步就从略了.这里着重分享一下如何求答案. ...
- 洛谷3233 HNOI2014(虚树+dp)
膜拜一发\(mts\_246,forever\_shi\) 这两位爷是真的无敌! 首先来看这个题,一看题目的数据范围和"关键点"字眼,我们就能得知这是一道虚树题 那就先一如既往的建 ...
随机推荐
- .NET高级调试之sos命令输出看不懂怎么办
一:背景 1. 讲故事 很多.NET开发者在学习高级调试的时候,使用sos的命令输出会发现这里也看不懂那里也看不懂,比如截图中的这位朋友. .NET高级调试属于一个偏冷门的领域,国内可观测的资料比较少 ...
- 项目实战:Qt+ffmpeg摄像头检测工具
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- [golang] 变量声明和初始化 var, :=, new() 和 make()
[golang] 变量声明和初始化 var, :=, new() 和 make() 说明 go语言中,提供了多种变量声明和初始化的方法.这里着重一一说明.并提供一个简单的指南. 指南 使用make() ...
- 【Azure Key Vault】.NET 代码如何访问中国区的Key Vault中的机密信息(Get/Set Secret)
问题描述 使用 .NET Azure.Identity 中的 DefaultAzureCredential 认证并连接到Azure Key Vault中, 在Key Vault 的示例中,并没有介绍如 ...
- C++ STL 容器-string类型
C++ STL 第一部分-容器 STL的介绍 C++的STL分为六大部分 容器分为 容器的概念 容器内元素的条件 1.必须可以复制copy或者搬移move,包括条件是在拷贝和搬移的过程中不存在副作用. ...
- 一: Mysql字符集问题
## Mysql 字符集问题 1 修改MySQL5.7字符集 1.1 修改步骤 在MySQL 8.0版本之前,默认字符集为 latin1 ,utf8字符集指向的是 utf8mb3 .网站开发人员在数据 ...
- vscode 切换项目快捷键 Alt + Shift + P 插件 Project Manager
vscode 切换项目快捷键 Alt + Shift + P 插件 Project Manager 需求 快速切换同时打开的项目 解决方案 Alt + Shift + P 话说这个插件很早就用了,但是 ...
- 基于泰凌微TLSR825x的数据透传解决方案之源码解析
一 概念 串口透传也叫透明传输,简称透传.串口透传是一种工作方式,一般出现在串口蓝牙模块中.串口透传蓝牙模块使用极其便利,开发者不需要了解蓝牙协议栈是如何实现的,只需要使用串口蓝牙模块就可以方便地开发 ...
- 使用POI操作Excel时new XSSFWorkbook ()报错java.lang.NoSuchMethodError解决方案
使用最新的POI3.11时,在运行 Workbook workBook = new XSSFWorkbook ();这段代码时出现错误: java.lang.NoSuchMethodError: j ...
- .net core 多线程下使用 Random 会出现bug
.net core 多线程下使用 Random 会出现的bug 先看原文: Working with System.Random and threads safely in .NET Core and ...