bzoj千题计划255:bzoj3572: [Hnoi2014]世界树
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]世界树的更多相关文章
- bzoj千题计划300:bzoj4823: [Cqoi2017]老C的方块
http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...
- bzoj千题计划196:bzoj4826: [Hnoi2017]影魔
http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...
- bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪
http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...
- bzoj千题计划177:bzoj1858: [Scoi2010]序列操作
http://www.lydsy.com/JudgeOnline/problem.php?id=1858 2018 自己写的第1题,一遍过 ^_^ 元旦快乐 #include<cstdio> ...
- bzoj千题计划317:bzoj4650: [Noi2016]优秀的拆分(后缀数组+差分)
https://www.lydsy.com/JudgeOnline/problem.php?id=4650 如果能够预处理出 suf[i] 以i结尾的形式为AA的子串个数 pre[i] 以i开头的形式 ...
- bzoj千题计划304:bzoj3676: [Apio2014]回文串(回文自动机)
https://www.lydsy.com/JudgeOnline/problem.php?id=3676 回文自动机模板题 4年前的APIO如今竟沦为模板,,,╮(╯▽╰)╭,唉 #include& ...
- bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹
http://www.lydsy.com/JudgeOnline/problem.php?id=2244 每枚导弹成功拦截的概率 = 包含它的最长上升子序列个数/最长上升子序列总个数 pre_len ...
- bzoj千题计划278:bzoj4590: [Shoi2015]自动刷题机
http://www.lydsy.com/JudgeOnline/problem.php?id=4590 二分 这么道水题 没long long WA了两发,没判-1WA了一发,二分写错WA了一发 最 ...
- bzoj千题计划250:bzoj3670: [Noi2014]动物园
http://www.lydsy.com/JudgeOnline/problem.php?id=3670 法一:KMP+st表 抽离nxt数组,构成一棵树 若nxt[i]=j,则i作为j的子节点 那么 ...
随机推荐
- js 边写边出现刚写的内容
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- ReactJS实用技巧(2):从新人大坑——表单组件来看State
不太清楚有多少初学React的同学和博主当时一样,在看完React的生命周期.数据流之后觉得已经上手了,甩开文档啪啪啪的开始敲了起来.结果...居然被一个input标签给教做人了. 故事是这样的:首先 ...
- 关于App自动化执行链接Appium服务包名正确但是报错An unknown server-side error occurred while processing the command
在执行链接Appium服务时连接失败可能原因: 1.报错截图: 2.先检查包名是否正确(正常情况下包名不会错误)通过命令行查看包名:aapt dump badging xxx.apk 3.检查对应包的 ...
- manjaro安装软件
fcitx 安装以下包 fcitx-googlepinyin kcm-fcitx 安装了输入法之后,还要在/etc/profile或~/.xprofile里添加如下内容: export GTK_IM_ ...
- commitizen和cz-customizable配置git commit message
起因 团队对提交的commit message格式有约定俗称的要求,但是没有一个统一的规范,导致大家提交的commit message或多或少不太一样.因此,需要一个工具来帮助大家统一commit m ...
- Java 8 新特性---------Stream
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据. Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象 ...
- 2-Fourteenth Scrum Meeting-20151214
任务安排 成员 今日完成 明日任务 闫昊 用本地数据库记录课程结构和学习进度 修复bug 唐彬 请假(编译……) 编写与服务器交互的代码 史烨轩 请假(编译……) 获取视频url 余帆 请假( ...
- Linux内核分析第一周——计算机是如何工作的
冯诺依曼体系结构 核心思想 1.冯诺依曼是:数字计算机的数制采用二进制:计算机应该按照程序顺序执行. 2.采用二进制作为计算机数值计算的基础,以0.1代表数值.不采用人类常用的十进制计数方法,二进制使 ...
- 转发npm发布包的过程
老板,来个npm账号! 因为你的包是要放在npm上的,所以,没有npm的账号,根本什么活都干不了. 在npm上注册一个账号是很简单的,随便填一下用户名密码邮箱,然后人家就会发个邮件给你,然后就注册成功 ...
- [Latex] Travis-CI与Latex构建开源中文PDF
博主有一本开源书籍,用 latex 排版,托管在Github上.但用 latex 不像是 Markdown,当tex文本更新时,用于最终浏览的PDF文件很难得到及时的更新, 所以博主一直想找到一套工具 ...