题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3572


算是细节题了吧。。

  构出虚树,考虑z正反DP两次求出虚树中每个点最近的议事处是哪一个点,然后枚举虚树中的每一条边${X->Y}$,对于两点间在原树中的路径,显然存在一个分界点使得自分界点之上的所有点归最靠近$X$的议事处管辖,之下的点归最靠经$Y$的议事处管辖,还有一些没有考虑过的点,另外统计一下即可。


 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
#define maxn 310000
#define llg long long
#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
llg n,m,f[maxn][],deep[maxn],dfn[maxn],cnt,size[maxn],s[maxn],top;
llg a[maxn],b[maxn],bel[maxn],c[maxn],rem[maxn],ans[maxn]; vector<llg>g[maxn]; bool cmp(llg x,llg y) {return dfn[x]<dfn[y];} void link(llg x,llg y){g[x].push_back(y);} void dfs(llg x,llg fa)
{
dfn[x]=++cnt;
llg w=g[x].size(),v;
size[x]=;
for (llg i=;i<w;i++)
{
v=g[x][i];
if (v==fa) continue;
deep[v]=deep[x]+;
f[v][]=x;
dfs(v,x);
size[x]+=size[v];
}
} void make_f()
{
for (llg j=;j<=;j++)
for (llg i=;i<=n;i++)
f[i][j]=f[f[i][j-]][j-];
} llg lca(llg x,llg y)
{
if (deep[x]<deep[y]) swap(x,y);
for (llg i=;i>=;i--)
if (deep[f[x][i]]>=deep[y])
x=f[x][i];
if (x==y) return x;
for (llg i=;i>=;i--)
if (f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
return f[x][];
} llg dis(llg x,llg y) {return deep[x]+deep[y]-*deep[lca(x,y)];} void init()
{
cin>>n;
llg x,y;
for (llg i=;i<n;i++)
{
scanf("%lld%lld",&x,&y);
g[x].push_back(y),g[y].push_back(x);
}
deep[]=;
dfs(,-);
make_f();
} void build_tree()
{
cnt=top=;
sort(a+,a+m+,cmp);
if (bel[]!=) s[++top]=;
for (llg i=;i<=m;i++)
{
llg x=a[i],fa=;
while (top)
{
fa=lca(s[top],x);
if (top> && deep[fa]<deep[s[top-]])
{
link(s[top-],s[top]);
top--;
}
else
if (deep[fa]<deep[s[top]]){ link(fa,s[top--]); break;}
else
break; }
if (s[top]!=fa) s[++top]=fa;
s[++top]=x;
}
while (--top) link(s[top],s[top+]);
} void dfs1(llg x,llg fa)
{
c[++cnt]=x;
rem[x]=size[x];
llg w=g[x].size(),v;
for (llg i=;i<w;i++)
{
v=g[x][i];
dfs1(v,x);
if (v==fa) continue;
if (!bel[v]) continue;//why
llg d1=dis(bel[v],x),d2=dis(bel[x],x);
if ((d1==d2 && bel[v]<bel[x]) || (d1<d2) || !bel[x]) bel[x]=bel[v];
}
} void dfs2(llg x,llg fa)
{
llg w=g[x].size(),v;
for (llg i=;i<w;i++)
{
v=g[x][i];
if (v==fa) continue;
llg d1=dis(bel[x],v),d2=dis(bel[v],v);
if ((d1==d2 && bel[v]>bel[x]) || (d1<d2) || !bel[v])
bel[v]=bel[x];
dfs2(v,x);
}
} void work(llg x,llg y)
{
llg son=y,mid=y;
for (llg i=;i>=;i--)
if (deep[f[son][i]]>deep[x]) son=f[son][i];
rem[x]-=size[son];
if (bel[x]==bel[y]) {ans[bel[x]]+=size[son]-size[y]; return;}
for (llg i=;i>=;i--)
{
llg ne=f[mid][i];
if (deep[ne]<=deep[x]) continue;
llg d1=dis(bel[x],ne),d2=dis(bel[y],ne);
if (d1>d2 || (d1==d2 && bel[y]<bel[x])) mid=ne;
}
ans[bel[x]]+=size[son]-size[mid];
ans[bel[y]]+=size[mid]-size[y];
} int main()
{
yyj("tree");
init();
llg T; cin>>T;
for (llg i=;i<=n;i++)
{
while (!g[i].empty()) g[i].pop_back();
//std::vector(c).swap(vec);
}
while (T--)
{
scanf("%lld",&m);
for (llg i=;i<=m;i++)
{
scanf("%lld",&a[i]);
b[i]=a[i]; bel[a[i]]=a[i];
}
build_tree();
dfs1(,-); dfs2(,-);
for (llg i=;i<=cnt;i++)
{
llg w=g[c[i]].size();
llg la=-;
for (llg j=;j<w;j++)
{
if (g[c[i]][j]==la) continue;
la=g[c[i]][j];
work(c[i],g[c[i]][j]);
}
}
for (llg i=;i<=cnt;i++) ans[bel[c[i]]]+=rem[c[i]];
for (llg i=;i<=m;i++) printf("%lld ",ans[b[i]]);
printf("\n");
for (llg i=;i<=cnt;i++)
{
ans[c[i]]=bel[c[i]]=rem[c[i]]=;
while (!g[c[i]].empty()) g[c[i]].pop_back();
}
}
return ;
}

【BZOJ】3572: [Hnoi2014]世界树的更多相关文章

  1. BZOJ 3572: [Hnoi2014]世界树

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

  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)

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

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

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

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

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

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

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

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

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

  8. BZOJ 3572: [Hnoi2014]世界树 [虚树 DP 倍增]

    传送门 题意: 一棵树,多次询问,给出$m$个点,求有几个点到给定点最近 写了一晚上... 当然要建虚树了,但是怎么$DP$啊 大爷题解传送门 我们先求出到虚树上某个点最近的关键点 然后枚举所有的边$ ...

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

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

随机推荐

  1. python--元组tuple

    元组与列表一样,都是序列.但元组不能修改内容(列表允许) 默认的,元组通过圆括号括起来 1. 使用type函数查看类型 numbers = (1,2,3,4,5,6,7,8,9,0) print(ty ...

  2. python sqlite3 数据库操作

    python sqlite3 数据库操作 SQLite3是python的内置模块,是一款非常小巧的嵌入式开源数据库软件. 1. 导入Python SQLite数据库模块 import sqlite3 ...

  3. 安装ubuntu18.04.1

    下载ubuntu:https://www.ubuntu.com/download/desktop 在虚拟机创建好ubuntu18.04.1后无法启动(选择的是linux,ubuntu64位),提示:此 ...

  4. 基于 SSL 的 Nginx 反向代理

    基于 SSL 的 Nginx 反向代理 描述: 线上zabbix因机房网络问题,外网接口无法对外访问,因此采用同机房的另外一台服务器做反向代理. 线上用于zabbix提供web访问的Nginx,采用h ...

  5. Prometheus监控学习笔记之PromQL简单示例

    0x00 简单的时间序列选择 返回度量指标 http_requests_total 的所有时间序列样本数据: http_requests_total 返回度量指标名称为 http_requests_t ...

  6. 同级div设置display:inline-block,父级div强制不换行

    同级div设置display:inline-block,父级div强制不换行 <html> <head></head> <body> <div i ...

  7. Web视频播放之video.js

    h5这么火是有它的理由的,支持原生视频播放,但是目前兼容性还不是很好,因此使用js框架支持网站视频播放是比较不错的选择. 下载video.js,我们可以通过官网去下,但是官网在国外,我尝试了几次均下载 ...

  8. centos-6.5安装部署LNMP环境

    安装部署前,确保安装了gcc和gcc-c++ 系统信息: [root@zww ~]# cat /etc/redhat-release CentOS release 6.5 (Final) [root@ ...

  9. shell 变量相关的命令

    变量="变量" readonly 变量名="变量"  表示设置该变量为只读变量 ,这个变量不能别改变 echo $变量名 set  显示本地所有的变量 unse ...

  10. P2147 [SDOI2008]洞穴勘测

    P2147 [SDOI2008]洞穴勘测 思路 没办法,我就是喜欢板子都想发的人 都是基础操作,不多说了 代码 #include <bits/stdc++.h> #define ls ch ...