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. AutoCAD DevTV-AUTOCAD二次开发资源合集

    Webcast Language Date AutoCAD .Net - Session 2 English 13-Sep-12 AutoCAD .Net - Session 1 English 6- ...

  2. aarch64_l3

    librdmacm-utils-1.1.0-4.fc26.aarch64.rpm 2017-02-12 07:12 87K fedora Mirroring Project libreadline-j ...

  3. 一步一步搭建11gR2 rac+dg之DG 机器配置(七)【转】

    DG 机器配置 转自: 一步一步搭建11gR2 rac+dg之DG 机器配置(七)-lhrbest-ITPUB博客http://blog.itpub.net/26736162/viewspace-12 ...

  4. python网络编程--线程使用threading

    一:线程使用 线程使用有两种方法,一种是直接使用,二是通过继承threading.Thread类使用 二:函数式使用 函数式:调用thread模块中的start_new_thread()函数来产生新线 ...

  5. git ——本地项目上传到git

    1.(先进入项目文件夹)通过命令 git init 把这个目录变成git可以管理的仓库 git init 2.把文件添加到版本库中,使用命令 git add .添加到暂存区里面去,不要忘记后面的小数点 ...

  6. mongod 一些命令汇总

    1. 导出数据库: mongoexport -d master -c reports -o no.json --type json -f "title,name" -q '{&qu ...

  7. json字符串与java对象的相互转换(jackson)

    1.java对象转换为json字符串 package com.chichung.json; import com.fasterxml.jackson.core.JsonProcessingExcept ...

  8. java 内部类可以被覆盖吗

    如果创建了一个内部类,然后继承其外围类并重新定义内部类时,"覆盖"内部类就好像是其外围类的一个方法,并不起作用, 这两个内部类是完全独立的两个实体,各自在自己的命名空间内 //: ...

  9. HDU 5115 Dire Wolf (区间DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5115 题目大意:有一些狼,从左到右排列,每只狼有一个伤害A,还有一个伤害B.杀死一只狼的时候,会受到这 ...

  10. SQL农历转换函数(显示中文格式,加入润月的显示)

    if object_id('fn_getlunar') is not null drop function fn_getlunar go create function dbo.fn_getlunar ...