传送门

题意:

一棵树,多次询问,给出$m$个点,求有几个点到给定点最近


写了一晚上...

当然要建虚树了,但是怎么$DP$啊

大爷题解传送门

我们先求出到虚树上某个点最近的关键点

然后枚举所有的边$(f,x)$,讨论一下边上的点的子树应该靠谁更近

倍增求出分界点

注意有些没出现在虚树上的子树

注意讨论的时候只讨论链上的不包括端点,否则$f$的子树会被贡献多次

学到的一些$trick:$

1.$pair$的妙用

2.不需要建出虚树只要求虚树的$dfs$序(拓扑序)和$fa$就可以$DP$了

注意$DP$的时候必须先用儿子更新父亲再用父亲更新儿子,因为父亲的最优值有可能在其他儿子

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define pii pair<int,int>
#define MP make_pair
#define fir first
#define sec second
typedef long long ll;
const int N=3e5+,INF=1e9;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} int n,Q;
struct Edge{
int v,ne,w;
}e[N<<];
int cnt,h[N];
inline void ins(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
int fa[N][],deep[N],dfn[N],dfc,size[N],All;
void dfs(int u){
dfn[u]=++dfc;
size[u]=;
for(int i=;(<<i)<=deep[u];i++)
fa[u][i]=fa[ fa[u][i-] ][i-];
for(int i=h[u];i;i=e[i].ne)
if(e[i].v!=fa[u][]){
fa[e[i].v][]=u;
deep[e[i].v]=deep[u]+;
dfs(e[i].v);
size[u]+=size[e[i].v];
}
}
inline int lca(int x,int y){
if(deep[x]<deep[y]) swap(x,y);
int bin=deep[x]-deep[y];
for(int i=;i>=;i--)
if((<<i)&bin) x=fa[x][i];
for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return x==y ? x :fa[x][];
} int a[N],st[N],par[N],dis[N],t[N],m,ans[N];
int remain[N];
inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
inline void ins2(int x,int y){par[y]=x;dis[y]=deep[y]-deep[x];}
pii g[N];
void dp(int m){
for(int i=m;i>;i--){
int x=t[i],f=par[x];
g[f]=min(g[f],MP(g[x].fir+dis[x],g[x].sec));
}
for(int i=;i<=m;i++){
int x=t[i],f=par[x];
g[x]=min(g[x],MP(g[f].fir+dis[x],g[f].sec));
}
}
inline int jump1(int x,int tar){
for(int i=;i>=;i--)
if(deep[ fa[x][i] ]>=tar) x=fa[x][i];
return x;
}
inline int jump(int x,int tar){
int bin=deep[x]-tar;
for(int i=;i>=;i--)
if((<<i)&bin) x=fa[x][i];
return x;
}
int ora[N];
void solve(){
int n=read(),m=;
for(int i=;i<=n;i++)
ora[i]=a[i]=read(),t[++m]=a[i],g[a[i]]=MP(,a[i]);
sort(a+,a++n,cmp); int top=;
for(int i=;i<=n;i++){
if(!top) {st[++top]=a[i];continue;}
int x=a[i],f=lca(x,st[top]);
while(dfn[f]<dfn[st[top]]){
if(dfn[f]>=dfn[st[top-]]){
ins2(f,st[top--]);
if(f!=st[top]) st[++top]=f,t[++m]=f,g[f]=MP(INF,);
break;
}else ins2(st[top-],st[top]),top--;
}
st[++top]=x;
}
while(top>) ins2(st[top-],st[top]),top--; sort(t+,t++m,cmp);
dp(m);
for(int i=;i<=m;i++) remain[t[i]]=size[t[i]]; ans[ g[t[]].sec ]+=All-size[t[]];
for(int i=;i<=m;i++){
int x=t[i],f=par[x];par[x]=;
int t=jump(x,deep[f]+);
remain[f]-=size[t];
if(g[x].sec == g[f].sec) ans[ g[x].sec ]+=size[t]-size[x];
else{
int len=g[x].fir + g[f].fir + dis[x], mid=deep[x]-(len/-g[x].fir);
if( !(len&) && g[f].sec<g[x].sec ) mid++;
int y=jump(x,mid);
ans[ g[f].sec ]+=size[t]-size[y];
ans[ g[x].sec ]+=size[y]-size[x];
}
}
for(int i=;i<=m;i++) ans[ g[t[i]].sec ]+=remain[t[i]];
for(int i=;i<=n;i++) printf("%d%c",ans[ora[i]],i==n?'\n':' '),ans[ora[i]]=;
}
int main(){
//freopen("in","r",stdin);
n=read();All=n;
for(int i=;i<n;i++) ins(read(),read());
dfs();
Q=read();
while(Q--) solve();
}

BZOJ 3572: [Hnoi2014]世界树 [虚树 DP 倍增]的更多相关文章

  1. BZOJ 3572 [HNOI2014]世界树 (虚树+DP)

    题面:BZOJ传送门 洛谷传送门 题目大意:略 细节贼多的虚树$DP$ 先考虑只有一次询问的情况 一个节点$x$可能被它子树内的一个到x距离最小的特殊点管辖,还可能被管辖fa[x]的特殊点管辖 跑两次 ...

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

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

  3. BZOJ 3572: [Hnoi2014]世界树 虚树 树形dp

    https://www.lydsy.com/JudgeOnline/problem.php?id=3572 http://hzwer.com/6804.html 写的时候参考了hzwer的代码,不会写 ...

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

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

  5. bzoj 3572 [Hnoi2014]世界树——虚树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3572 关于虚树:https://www.cnblogs.com/zzqsblog/p/556 ...

  6. bzoj 3572: [Hnoi2014]世界树 虚树

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

  7. 【BZOJ】3572: [Hnoi2014]世界树 虚树+倍增

    [题意]给定n个点的树,m次询问,每次给定ki个特殊点,一个点会被最近的特殊点控制,询问每个特殊点控制多少点.n,m,Σki<=300000. [算法]虚树+倍增 [题解]★参考:thy_asd ...

  8. 洛谷 P3233 [HNOI2014]世界树(虚树+dp)

    题面 luogu 题解 数据范围已经告诉我们是虚树了,考虑如何在虚树上面\(dp\) 以下摘自hzwer博客: 构建虚树以后两遍dp处理出虚树上每个点最近的议事处 然后枚举虚树上每一条边,考虑其对两端 ...

  9. BZOJ 3572: [Hnoi2014]世界树

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

随机推荐

  1. 刨根问底:什么是yum源,yum的工作原理又是什么

    1.刨根问底---什么是yum源?yum的工作原理? 说到yum源就必须说到linux系统中特有的依赖关系问题,yum就是为了解决依赖关系而存在的.yum源就相当是一个目录项,当我们使用yum机制安装 ...

  2. [国嵌攻略][162][USB协议分析]

    USB设备逻辑结构 在USB设备的逻辑组织中,包含设备.配置.接口和端点4个层次.设备通常有一个或多个配置,配置通常有一个或多个接口,接口通常有零个或多个端点. USB设备描述符 当我们把USB设备( ...

  3. JavaScript变量声明与提升

    一直以来对变量提升都是比较模糊的,今天特地看了一下这个知识点,总结一下. 1.举个最简单的例子来说一下什么是变量提升吧. function foo(){ console.log(x); // unde ...

  4. UE4 UnLoadStreamLevel

    今天测试发现一个bug记录一下,如果把某一个子关卡的加载方式设置为Always Loaded时,调用UnloadStreamLevel时不会执行Completed后面的节点,也就是一直没有完成.

  5. 如何设置让网站禁止被爬虫收录?robots.txt

    robot.txt只是爬虫禁抓协议,user-agent表示禁止哪个爬虫,disallow告诉爬出那个禁止抓取的目录. 如果爬虫够友好的话,会遵守网站的robot.txt内容. 一个内部业务系统,不想 ...

  6. JavaSE笔记-异常

    Java 异常 Throwable类的体系结构(一些常用的) 异常分类 checked,unchecked 区分:RuntimeException及其子类,Error类及其子类,是unchecked ...

  7. Shell中$X的含义

    $0 表示这个程序的执行名字,包含输入参数$n 表示这个程序的第n个参数值$*  表示这个程序的所有参数,此选项参数可超过9个.$#  表示这个程序的参数个数$$  表示这个程序的PID(脚本运行的当 ...

  8. vue 开发2017年变化回顾及2018年展望

    vue.js 变化 从 github 的发布记录我们可以看到2017年 vue.js 的第一个发布为 v2.1.9,最后一个为 v2.5.13,主要发布小版本 2.2~2.5.这些发布提升了vue 与 ...

  9. JSP页面中的pageEncoding和contentType的区别

    <%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> pag ...

  10. 【jsp】MyEclipse10.7.1最新版+破解下载

    MyEclipse企业级工作平台[1](MyEclipse Enterprise Workbench ,简称MyEclipse)是对EclipseIDE的扩展,利用它我们可以在数据库和JavaEE的开 ...