博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj千题计划255:bzoj3572: [Hnoi2014]世界树
阅读量:6045 次
发布时间:2019-06-20

本文共 2881 字,大约阅读时间需要 9 分钟。

 

明显需要构造虚树

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

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
#include
#include
#include
#define N 300001typedef long long LL;#define min(x,y) ((x)<(y) ? (x) : (y))int n,lim;int num,id[N];int fa[N][19],SIZ[N],prefix[N],dep[N];void read(int &x){ x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0';c=getchar(); }}namespace Original{ int front[N],nxt[N<<1],to[N<<1]; 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]=1; int t; for(int i=front[x];i;i=nxt[i]) { t=to[i]; if(t!=fa[x][0]) { fa[t][0]=x; dep[t]=dep[x]+1; dfs(t); SIZ[x]+=SIZ[t]; } } } void multiplication() { lim=log(n)/log(2); for(int i=1;i<=lim;++i) for(int j=1;j<=n;++j) fa[j][i]=fa[fa[j][i-1]][i-1]; } void Prefix_dfs(int x) { int t; for(int i=front[x];i;i=nxt[i]) { t=to[i]; if(t!=fa[x][0]) { prefix[t]=prefix[x]+SIZ[x]-SIZ[t]; Prefix_dfs(t); } } } void main() { int u,v; read(n); for(int i=1;i
=0;--i) if(y>=(1<
=0;--i) if(id[fa[x][i]]>id[y]) x=fa[x][i]; return fa[x][0]; } int get_dis(int u,int v) { int lca=get_lca(u,v); return dep[u]+dep[v]-dep[lca]*2; } void build() { std::sort(use+1,use+cnt+1,cmp); tot=0; st[top=1]=1; bin[bin_cnt=1]=1; siz[1]=SIZ[1]; int i=1; if(use[1]==1) i=2; int x,lca; for(;i<=cnt;++i) { x=use[i]; lca=get_lca(x,st[top]); while(id[lca]
=id[st[top-1]]) { 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-1],st[top],dep[st[top]]-dep[st[top-1]]); top--; } st[++top]=x; siz[x]+=SIZ[x]; bin[++bin_cnt]=x; } while(top>1) { add(st[top-1],st[top],dep[st[top]]-dep[st[top-1]]); top--; } } int dfs1(int x) { int p,d; mi[x]=0; 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
>1; f=find_ancestor(v,mid); down=get_dis(f,bl[v]); up=get_dis(f,bl[u]); if(down

 

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/8497215.html

你可能感兴趣的文章
移动互联网,入口生死战
查看>>
JAVA多线程深度解析
查看>>
Kafka High Level Consumer 会丢失消息
查看>>
时间轴
查看>>
java 获取系统当前时间的方法
查看>>
Ubuntu 10.04升级git 到1.7.2或更高的可行方法
查看>>
Spring Security4实战与原理分析视频课程( 扩展+自定义)
查看>>
第一周博客作业
查看>>
thinkpython2
查看>>
oracle recyclebin与flashback drop
查看>>
svmlight使用说明
查看>>
Swing 和AWT之间的关系
查看>>
Mysql设置自增长主键的初始值
查看>>
Android计时器正确应用方式解析
查看>>
获取post传输参数
查看>>
ASP生成静态页面的方法
查看>>
HDU 1325 Is It A Tree? 判断是否为一棵树
查看>>
Bzoj 2252: [2010Beijing wc]矩阵距离 广搜
查看>>
算术运算表达式正则及分析
查看>>
Oracle 12c 多租户 手工创建 pdb 与 手工删除 pdb
查看>>