https://www.lydsy.com/JudgeOnline/problem.php?id=3572

http://hzwer.com/6804.html 写的时候参考了hzwer的代码,不会写的题读一遍代码就好了(所以菜)。

虚树还是老一套,树形dp的部分比较有趣。

通过dfs两遍(从下往上总结一遍,从上往下再一遍)把每个点所归属的点找到。

对于那些没有出现在虚树中的点,对通过每条虚树上的边进行总结找到每两个点之间没有统计的点的归属(这个归属一定为bel[x]或bel[y])。

通过倍增中用lca找到距离判断来找每条边上分割点(可以发现需要找的是那种 bel[x] 和 bel[y] 在边两边的边, bel[x] 和 bel[y] 不在边两边时一定 bel[x] = bel[y] ),

那么对 bel[x] 的贡献为:siz[x在这条边上的第一个孩子] - siz[分割点] ,

对 bel[y] 的贡献为:siz[分割点] - siz[y] 。

还要注意一下那些作为某个虚树中的点的子树出现的点块,这些点是属于它的根(姑且这么说吧)的归属的,这部分贡献是在对边的统计结束后在统计虚树中每个点的归属时计算的。

说起来有点麻烦,读代码吧。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
using namespace std;
#define LL long long
const int maxn=;
int n,m,Q;
struct nod{
int y,next;
}e[maxn*];
int head[maxn]={},tot=;
int dep[maxn]={},id[maxn]={},siz[maxn]={},fa[maxn][]={},cnt=;
int a[maxn]={},bel[maxn]={},sta[maxn]={},tai=;
int c[maxn]={},re[maxn],tly=;
int f[maxn]={},b[maxn]={};
inline void init(int x,int y){e[++tot].y=y;e[tot].next=head[x];head[x]=tot;}
bool mcmp(int x,int y){
return id[x]<id[y];
}
void dfs(int x){
int y; siz[x]=; id[x]=++cnt;
for(int i=;i<=;i++)fa[x][i]=fa[fa[x][i-]][i-];
for(int i=head[x];i;i=e[i].next){
y=e[i].y; if(y==fa[x][])continue;
fa[y][]=x; dep[y]=dep[x]+; dfs(y);
siz[x]+=siz[y];
}
}
inline int getlca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=;i>=;--i)if(dep[fa[x][i]]>=dep[y])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][];
}
inline int getdis(int x,int y){
return dep[x]+dep[y]-*dep[getlca(x,y)];
}
void dfs1(int x){//get every points'bel[]
c[++tly]=x;re[x]=siz[x];
for(int i=head[x];i;i=e[i].next){
int y=e[i].y;
dfs1(y);if(bel[y]==)continue;
if(bel[x]==){bel[x]=bel[y];continue;}
int d1=getdis(bel[y],x),d2=getdis(bel[x],x);
if(d1<d2||(d1==d2&&bel[y]<bel[x]))bel[x]=bel[y];
}
}
void dfs2(int x){
for(int i=head[x];i;i=e[i].next){
int y=e[i].y;
if(bel[y]==)bel[y]=bel[x];
else{
int d1=getdis(bel[y],y),d2=getdis(bel[x],y);
if(d1>d2||(d1==d2&&bel[y]>bel[x]))bel[y]=bel[x];
}
dfs2(y);
}
}
void doit(int x,int y){
int son=y,mid=y;
for(int i=;i>=;--i)
if(dep[fa[son][i]]>dep[x])son=fa[son][i];
//cout<<x<<y<<son<<endl;
re[x]-=siz[son];
if(bel[x]==bel[y]){f[bel[x]]+=siz[son]-siz[y];return;}
for(int i=;i>=;--i){
int nxt=fa[mid][i];
if(dep[nxt]<dep[son])continue;
int d1=getdis(nxt,bel[x]),d2=getdis(nxt,bel[y]);
if(d1>d2||(d1==d2&&bel[y]<bel[x]))mid=nxt;
}
f[bel[x]]+=siz[son]-siz[mid];
f[bel[y]]+=siz[mid]-siz[y];
}
void solve(){
tot=;tly=;
scanf("%d",&m);
for(int i=;i<=m;i++){scanf("%d",&a[i]);b[i]=a[i];bel[a[i]]=a[i];}
sort(a+,a++m,mcmp);
if(a[]!=)sta[++tai]=;
sta[++tai]=a[];
for(int i=;i<=m;i++){
int lc=getlca(sta[tai],a[i]);
while(dep[sta[tai]]>dep[lc]){
if(dep[sta[tai-]]<=dep[lc]){init(lc,sta[tai]);--tai;break;}
init(sta[tai-],sta[tai]);tai--;
}
if(lc!=sta[tai])sta[++tai]=lc;
if(a[i]!=sta[tai])sta[++tai]=a[i];
}
while(--tai)init(sta[tai],sta[tai+]);
dfs1();dfs2();
for(int i=;i<=tly;i++){
for(int j=head[c[i]];j;j=e[j].next){
doit(c[i],e[j].y);
}
}
for(int i=;i<=tly;i++)f[bel[c[i]]]+=re[c[i]];
for(int i=;i<m;i++)printf("%d ",f[b[i]]);
printf("%d\n",f[b[m]]);
for(int i=;i<=tly;i++){head[c[i]]=;bel[c[i]]=;f[c[i]]=;re[c[i]]=;}
}
int main(){
//freopen("a.in","r",stdin);
scanf("%d",&n);
int x,y;
for(int i=;i<n;i++){scanf("%d%d",&x,&y);init(x,y);init(y,x);}
dep[]=;dfs();
scanf("%d",&Q);
memset(head,,sizeof(head));
for(int i=;i<=Q;i++)solve();
return ;
}

BZOJ 3572: [Hnoi2014]世界树 虚树 树形dp的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. 【BZOJ-3572】世界树 虚树 + 树形DP

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

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

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

  8. BZOJ.2286.[SDOI2011]消耗战(虚树 树形DP)

    题目链接 BZOJ 洛谷P2495 树形DP,对于每棵子树要么逐个删除其中要删除的边,要么直接断连向父节点的边. 如果当前点需要删除,那么直接断不需要再管子树. 复杂度O(m*n). 对于两个要删除的 ...

  9. BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp 动态规划 dfs序

    https://www.lydsy.com/JudgeOnline/problem.php?id=2286 wa了两次因为lca犯了zz错误 这道题如果不多次询问的话就是裸dp. 一棵树上多次询问,且 ...

随机推荐

  1. 跨站请求伪造(CSRF)攻击原理解析:比你所想的更危险

    跨站请求伪造(CSRF)攻击原理解析:比你所想的更危险 跨站请求伪造(Cross-Site Request Forgery)或许是最令人难以理解的一种攻击方式了,但也正因如此,它的危险性也被人们所低估 ...

  2. 深拷贝数组 np.copy

    数组对象自带了浅拷贝和深拷贝的方法,但是一般用深拷贝多一些: 代码如下: >>> a = np.ones((2,2)) >>> b = a >>> ...

  3. linux arm mmu基础【转】

    转自:http://blog.csdn.net/xiaojsj111/article/details/11065717 ARM MMU页表框架 先上一张arm mmu的页表结构的通用框图(以下的论述都 ...

  4. github 优秀的开源项目

    https://github.com/wlcaption/AndroidMarket---- 这是手机应用商店,包含应用的下载,用户中心等内容 https://github.com/wlcaption ...

  5. linux之发送邮件--sendmail服务配置

    新手入门也不知道什么日志分析服务好,鸟哥说logwatch,那我就从logwatch开始吧! logwatch用到了emai发邮件,先从配置邮件发送sendmail开始: 安装sendmail服务,我 ...

  6. Linux 命令find、grep

    本文就向大家介绍find.grep命令,他哥俩可以算是必会的linux命令,我几乎每天都要用到他们.本文结构如下: find命令 find命令的一般形式 find命令的常用选项及实例 find与xar ...

  7. Kubernetes监控:部署Heapster、InfluxDB和Grafana

    本节内容: Kubernetes 监控方案 Heapster.InfluxDB和Grafana介绍 安装配置Heapster.InfluxDB和Grafana 访问 grafana 访问 influx ...

  8. Aspose.Words 自定义文档模版生成操作类

    /// <summary> /// 操作word通用类 LIYOUMING add 2017-12-27 /// </summary> public class DocHelp ...

  9. day7 面向对象class()学习

        面向过程 VS 面向对象     编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程,一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓 ...

  10. Rookey.Frame之实体表单验证

    昨天给大家介绍了实体FluentValidation验证,今天继续给大家介绍表单验证,在Rookey.Frame框架中,表单验证有PrimaryKeyFields字段验证.唯一验证.必填验证.常用验证 ...