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

明显需要构造虚树

点属于谁管理分三种情况:

1、属于虚树的点

2、在虚树上的边上的点

3、既不属于虚树的点,又不属于虚树上的边的点

第一种情况:

先做一遍树形dp,得到子树中距离它最近的点

再dfs一遍,看看父节点那一块 是否有比它现在的点更近的点

第二种情况:

一条边u-->v 如果u和v属于同一点x管理,那么这条边所代表的所有点也都属于x管理

否则的话,二分一个点tmp,tmp以上的点归管理u的点管理,tmp及tmp以下的点归管理v的点管理

第三种情况:

归这个种树的根 的父节点 管理

第三种情况可以合并到第一种情况中,即用siz[x]表示虚树中一个点x在原树代表多少个点

开始siz[x]=原树中x的子树大小

虚树中每加一条边x-->y,若y属于x的子节点中k的子树,就在siz[x]中减去 原树中k的子树大小

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm> #define N 300001 typedef long long LL; #define min(x,y) ((x)<(y) ? (x) : (y)) int n,lim;
int num,id[N];
int fa[N][],SIZ[N],prefix[N],dep[N]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-'';c=getchar(); }
} namespace Original
{
int front[N],nxt[N<<],to[N<<];
int tot; void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
} void dfs(int x)
{
id[x]=++num;
SIZ[x]=;
int t;
for(int i=front[x];i;i=nxt[i])
{
t=to[i];
if(t!=fa[x][])
{
fa[t][]=x;
dep[t]=dep[x]+;
dfs(t);
SIZ[x]+=SIZ[t];
}
}
} void multiplication()
{
lim=log(n)/log();
for(int i=;i<=lim;++i)
for(int j=;j<=n;++j)
fa[j][i]=fa[fa[j][i-]][i-];
} void Prefix_dfs(int x)
{
int t;
for(int i=front[x];i;i=nxt[i])
{
t=to[i];
if(t!=fa[x][])
{
prefix[t]=prefix[x]+SIZ[x]-SIZ[t];
Prefix_dfs(t);
}
}
} void main()
{
int u,v;
read(n);
for(int i=;i<n;++i)
{
read(u); read(v);
add(u,v);
}
dfs();
multiplication();
Prefix_dfs();
return;
}
} namespace Imaginary
{
int cnt,use[N]; int st[N],top; int tot;
int front[N],to[N],nxt[N],from[N],val[N]; int bin[N],bin_cnt; int siz[N]; int mi[N],bl[N];
int dy[N],ans[N]; bool cmp(int p,int q)
{
return id[p]<id[q];
} int find_ancestor(int x,int y)
{
for(int i=lim;i>=;--i)
if(y>=(<<i))
{
x=fa[x][i];
y-=(<<i);
}
return x;
} void add(int u,int v,int w)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; from[tot]=u; val[tot]=w;
int s=find_ancestor(v,dep[v]-dep[u]-);
siz[u]-=SIZ[s];
} int get_lca(int x,int y)
{
if(id[x]<id[y]) std::swap(x,y);
for(int i=lim;i>=;--i)
if(id[fa[x][i]]>id[y]) x=fa[x][i];
return fa[x][];
} int get_dis(int u,int v)
{
int lca=get_lca(u,v);
return dep[u]+dep[v]-dep[lca]*;
} void build()
{
std::sort(use+,use+cnt+,cmp);
tot=;
st[top=]=;
bin[bin_cnt=]=;
siz[]=SIZ[];
int i=;
if(use[]==) i=;
int x,lca;
for(;i<=cnt;++i)
{
x=use[i];
lca=get_lca(x,st[top]);
while(id[lca]<id[st[top]])
{
if(id[lca]>=id[st[top-]])
{
add(lca,st[top],dep[st[top]]-dep[lca]);
if(lca!=st[--top])
{
st[++top]=lca;
siz[lca]+=SIZ[lca];
bin[++bin_cnt]=lca;
}
break;
}
add(st[top-],st[top],dep[st[top]]-dep[st[top-]]);
top--;
}
st[++top]=x;
siz[x]+=SIZ[x];
bin[++bin_cnt]=x;
}
while(top>)
{
add(st[top-],st[top],dep[st[top]]-dep[st[top-]]);
top--;
}
} int dfs1(int x)
{
int p,d;
mi[x]=;
if(dy[x])
{
for(int i=front[x];i;i=nxt[i]) dfs1(to[i]);
bl[x]=x;
return x;
}
for(int i=front[x];i;i=nxt[i])
{
p=dfs1(to[i]);
d=dep[p]-dep[x];
if(!mi[x] || d<mi[x])
{
mi[x]=d;
bl[x]=p;
}
else if(d==mi[x] && p<bl[x]) bl[x]=p;
}
return bl[x];
} int dfs2(int x)
{
int t;
for(int i=front[x];i;i=nxt[i])
{
t=to[i];
if(!dy[t])
if(bl[x]!=bl[t])
{
if(mi[x]+val[i]<mi[t])
{
mi[t]=mi[x]+val[i];
bl[t]=bl[x];
}
else if(mi[x]+val[i]==mi[t] && bl[x]<bl[t]) bl[t]=bl[x];
}
dfs2(t);
}
ans[dy[bl[x]]]+=siz[x];
} void belong()
{
dfs1();
dfs2();
} void get_ans()
{
int f,s;
int l,r,mid,tmp,tmp_son;
int u,v;
bool equal;
int up,down;
for(int i=;i<=tot;++i)
{
u=from[i];
v=to[i];
r=dep[v]-dep[u]-;
if(!r) continue;
s=find_ancestor(v,r);
if(bl[u]==bl[v]) ans[dy[bl[u]]]+=prefix[v]-prefix[s];
else
{
tmp=v;
l=;
equal=false;
while(l<=r)
{
mid=l+r>>;
f=find_ancestor(v,mid);
down=get_dis(f,bl[v]);
up=get_dis(f,bl[u]);
if(down<up) tmp=f,l=mid+;
else if(down==up)
{
tmp=f;
equal=true;
tmp_son=find_ancestor(v,mid-);
break;
}
else r=mid-;
}
if(!equal)
{
ans[dy[bl[v]]]+=prefix[v]-prefix[tmp];
ans[dy[bl[u]]]+=prefix[tmp]-prefix[s];
}
else
{
ans[dy[bl[v]]]+=prefix[v]-prefix[tmp_son];
ans[dy[bl[u]]]+=prefix[tmp]-prefix[s];
ans[dy[min(bl[v],bl[u])]]+=prefix[tmp_son]-prefix[tmp];
}
}
}
for(int i=;i<=cnt;++i) printf("%d ",ans[i]);
printf("\n");
} void clear()
{
for(int i=;i<=bin_cnt;++i)
{
front[bin[i]]=;
ans[i]=;
dy[bin[i]]=;
siz[bin[i]]=;
}
tot=;
} void main()
{
int m;
read(m);
while(m--)
{
read(cnt);
for(int i=;i<=cnt;++i)
{
read(use[i]);
dy[use[i]]=i;
}
build();
belong();
get_ans();
clear();
}
return;
}
} int main()
{
Original::main();
Imaginary::main();
return ;
}

bzoj千题计划255:bzoj3572: [Hnoi2014]世界树的更多相关文章

  1. bzoj千题计划300:bzoj4823: [Cqoi2017]老C的方块

    http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...

  2. bzoj千题计划196:bzoj4826: [Hnoi2017]影魔

    http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...

  3. bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪

    http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...

  4. bzoj千题计划177:bzoj1858: [Scoi2010]序列操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=1858 2018 自己写的第1题,一遍过 ^_^ 元旦快乐 #include<cstdio> ...

  5. bzoj千题计划317:bzoj4650: [Noi2016]优秀的拆分(后缀数组+差分)

    https://www.lydsy.com/JudgeOnline/problem.php?id=4650 如果能够预处理出 suf[i] 以i结尾的形式为AA的子串个数 pre[i] 以i开头的形式 ...

  6. bzoj千题计划304:bzoj3676: [Apio2014]回文串(回文自动机)

    https://www.lydsy.com/JudgeOnline/problem.php?id=3676 回文自动机模板题 4年前的APIO如今竟沦为模板,,,╮(╯▽╰)╭,唉 #include& ...

  7. bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹

    http://www.lydsy.com/JudgeOnline/problem.php?id=2244 每枚导弹成功拦截的概率 = 包含它的最长上升子序列个数/最长上升子序列总个数 pre_len ...

  8. bzoj千题计划278:bzoj4590: [Shoi2015]自动刷题机

    http://www.lydsy.com/JudgeOnline/problem.php?id=4590 二分 这么道水题 没long long WA了两发,没判-1WA了一发,二分写错WA了一发 最 ...

  9. bzoj千题计划250:bzoj3670: [Noi2014]动物园

    http://www.lydsy.com/JudgeOnline/problem.php?id=3670 法一:KMP+st表 抽离nxt数组,构成一棵树 若nxt[i]=j,则i作为j的子节点 那么 ...

随机推荐

  1. js 边写边出现刚写的内容

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. ReactJS实用技巧(2):从新人大坑——表单组件来看State

    不太清楚有多少初学React的同学和博主当时一样,在看完React的生命周期.数据流之后觉得已经上手了,甩开文档啪啪啪的开始敲了起来.结果...居然被一个input标签给教做人了. 故事是这样的:首先 ...

  3. 关于App自动化执行链接Appium服务包名正确但是报错An unknown server-side error occurred while processing the command

    在执行链接Appium服务时连接失败可能原因: 1.报错截图: 2.先检查包名是否正确(正常情况下包名不会错误)通过命令行查看包名:aapt dump badging xxx.apk 3.检查对应包的 ...

  4. manjaro安装软件

    fcitx 安装以下包 fcitx-googlepinyin kcm-fcitx 安装了输入法之后,还要在/etc/profile或~/.xprofile里添加如下内容: export GTK_IM_ ...

  5. commitizen和cz-customizable配置git commit message

    起因 团队对提交的commit message格式有约定俗称的要求,但是没有一个统一的规范,导致大家提交的commit message或多或少不太一样.因此,需要一个工具来帮助大家统一commit m ...

  6. Java 8 新特性---------Stream

    Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据. Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象 ...

  7. 2-Fourteenth Scrum Meeting-20151214

    任务安排 成员 今日完成 明日任务 闫昊 用本地数据库记录课程结构和学习进度  修复bug 唐彬 请假(编译……)  编写与服务器交互的代码 史烨轩  请假(编译……)  获取视频url 余帆 请假( ...

  8. Linux内核分析第一周——计算机是如何工作的

    冯诺依曼体系结构 核心思想 1.冯诺依曼是:数字计算机的数制采用二进制:计算机应该按照程序顺序执行. 2.采用二进制作为计算机数值计算的基础,以0.1代表数值.不采用人类常用的十进制计数方法,二进制使 ...

  9. 转发npm发布包的过程

    老板,来个npm账号! 因为你的包是要放在npm上的,所以,没有npm的账号,根本什么活都干不了. 在npm上注册一个账号是很简单的,随便填一下用户名密码邮箱,然后人家就会发个邮件给你,然后就注册成功 ...

  10. [Latex] Travis-CI与Latex构建开源中文PDF

    博主有一本开源书籍,用 latex 排版,托管在Github上.但用 latex 不像是 Markdown,当tex文本更新时,用于最终浏览的PDF文件很难得到及时的更新, 所以博主一直想找到一套工具 ...