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的子节点 那么 ...
随机推荐
- 设计模式 笔记 中介者模式 Mediator
//---------------------------15/04/27---------------------------- //Mediator 中介者模式----对象行为型模式 /* 1:意 ...
- stl源码剖析 详细学习笔记deque(3)
protected: typedef simple_alloc<value_type,Alloc> data_allocator; //用来配置元素的alloc typedef simpl ...
- mongodump备份小量分片集群数据
1.使用mongodump备份小量分片集群数据 如果一个分片集群的数据集比较小,可以直接使用mongodump连接到mongos实例进行数据备份.默认情况下,mongodump到非primary的节点 ...
- docker之容器管理
一.docker常用的创建命令 [root@node03 ~]# docker create --help [root@node03 ~]# docker run --help OPTIONS说明: ...
- [转]申瓯 JSY2000-06 程控电话交换机呼叫转移设置
说明:若申瓯程控电话交换机分机有事不在位置上或遇忙分机正忙时为使某些重要来话不丢失,可设置将呼入本机的电话转移至其他分机及公网固定电话或手机.电话交换机使用了本功能不管分机用户在什么地方都能接听到办公 ...
- OD之绕过序列号验证(二)
上次是修改程序的标题,大家应该感觉这只是一个起点而已,接下来我们可以尝试绕过序列号验证,这种技术应用在很多软件中,比如淘宝上要买什么的软件,商家都会发给`你一个用户名和密码,而且还有试用期什么的,这确 ...
- python+Selenium 环境搭建
一.下载相关软件 1.python http://python.org/getit/ 2.setuptools http://pypi.python.org/pypi/setuptools 3.pip ...
- Kubernetes调用vSphere vSAN做持久化存储
参考 1.vSphere Storage for Kubernetes 2.IBM vSphere Cloud Provider 3.GitHub vSphere Volume examples 一. ...
- 2017-2018-2 1723《程序设计与数据结构》第三周作业 & 实验一 总结
作业地址 第三周作业:https://edu.cnblogs.com/campus/besti/CS-IMIS-1723/homework/1667 提交情况如图: 实验一:https://edu.c ...
- [51CTO]服务器虚拟化开源技术主流架构之争
服务器虚拟化开源技术主流架构之争 http://virtual.51cto.com/art/201812/589084.htm 大部分客户已经是KVM+OpenStack的架构了 我所见到的 工商云 ...