将$E_{i}$从小到大排序(显然不会相同),假设$E_{p_{i}}$为从小到大第$i$小

此时,必然有$E_{p_{1}}=1$,否则可以将$E_{p_{i}}$都减去$E_{p_{1}}-1$,之后即需要最小化$E_{p_{n}}$

当$p_{i}$确定后,题目中第2个条件即可变为$\forall 1\le i<j\le n,E_{p_{j}}-E_{p_{i}}\ge dist(p_{i},p_{j})$

取$j=i+1$时,即可推出$\forall 1\le i<n,E_{p_{i+1}}-E_{p_{i}}\ge dist(p_{i},p_{i+1})$

另一方面,此时即有$E_{p_{j}}-E_{p_{i}}=\sum_{k=i}^{j-1}E_{p_{k+1}}-E_{p_{k}}\ge \sum_{k=i}^{j-1}dist(p_{k},p_{k+1})\ge dist(p_{i},p_{j})$

(关于最后一个不等号,根据$dist(x,y)\le dist(x,z)+dist(z,y)$即可得到)

换言之,题目中第2个条件等价于$j=i+1$时的条件,那么$E_{p_{n}}$最小值即为$\sum_{i=1}^{n-1}dist(p_{i},p_{i+1})+1$

现在,问题即变为确定$p_{i}$,以最小化$E_{p_{n}}$(也即$\sum_{i=1}^{n-1}dist(p_{i},p_{i+1})+1$)

考虑将其补上$dist(p_{1},p_{n})$,此时考虑每一条边对答案的贡献,至少为2,且通过令$p_{i}$为dfs序来构造,可取到此下限,即和为$2(n-1)+1$

令$p_{1}$和$p_{n}$为树直径的两个端点,并以$p_{1}$为根优先搜索不包含$p_{n}$的子树即可构造出对应dfs序,令$d$为直径长度,则最终$E_{p_{n}}$即为$2(n-1)+1-d$

另外求$E_{i}$不需要求lca来求$dist(p_{i},p_{i+1})$,由于$\sum_{i=1}^{n-1}dist(p_{i},p_{i+1})$是$o(n)$的,直接在树上暴力移动,并判定其是否是后代即可

另外,题解中还提到了如何$o(n)$实现spj,只需要用桶排来对$p_{i}$排序,并以此判定相邻两者插值是否恰好为其距离即可

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 struct Edge{
5 int nex,to;
6 }edge[N<<1];
7 int E,n,x,y,head[N],dfn[N],f[N],sz[N],dep[N],P[N],ans[N];
8 bool check(int x,int y){
9 return (dfn[x]<=dfn[y])&&(dfn[y]<dfn[x]+sz[x]);
10 }
11 void add(int x,int y){
12 edge[E].nex=head[x];
13 edge[E].to=y;
14 head[x]=E++;
15 }
16 int dis(int x,int y){
17 int ans=0;
18 while (!check(x,y)){
19 ans++;
20 x=f[x];
21 }
22 while (!check(y,x)){
23 ans++;
24 y=f[y];
25 }
26 return ans;
27 }
28 void dfs(int k,int fa,int s){
29 dfn[k]=++dfn[0];
30 f[k]=fa;
31 sz[k]=1;
32 dep[k]=s;
33 for(int i=head[k];i!=-1;i=edge[i].nex)
34 if (edge[i].to!=fa){
35 dfs(edge[i].to,k,s+1);
36 sz[k]+=sz[edge[i].to];
37 }
38 }
39 void construct(int k,int fa){
40 P[++P[0]]=k;
41 for(int i=head[k];i!=-1;i=edge[i].nex)
42 if ((edge[i].to!=fa)&&(!check(edge[i].to,y)))construct(edge[i].to,k);
43 for(int i=head[k];i!=-1;i=edge[i].nex)
44 if ((edge[i].to!=fa)&&(check(edge[i].to,y)))construct(edge[i].to,k);
45 }
46 int main(){
47 scanf("%d",&n);
48 memset(head,-1,sizeof(head));
49 for(int i=1;i<n;i++){
50 scanf("%d%d",&x,&y);
51 add(x,y);
52 add(y,x);
53 }
54 dfs(1,0,0);
55 x=y=1;
56 for(int i=2;i<=n;i++)
57 if (dep[x]<dep[i])x=i;
58 dfs(x,0,0);
59 for(int i=2;i<=n;i++)
60 if (dep[y]<dep[i])y=i;
61 construct(x,0);
62 ans[P[1]]=1;
63 for(int i=1;i<n;i++)ans[P[i+1]]=ans[P[i]]+dis(P[i],P[i+1]);
64 for(int i=1;i<=n;i++)printf("%d ",ans[i]);
65 }

[ARC117D]Miracle Tree的更多相关文章

  1. Atcoder Regular Contest 117 D - Miracle Tree(分析性质+构造)

    Atcoder 题面传送门 笑死,阴间语文作业到现在还没写完,为了在这个点保持精神,我只好来颓篇题解辣 我们考虑探究一下怎么最小化 \(\max\limits_{i=1}^nE_i\),我们假设 \( ...

  2. QTREE5 - Query on a tree V——LCT

    QTREE5 - Query on a tree V 动态点分治和动态边分治用Qtree4的做法即可. LCT: 换根后,求子树最浅的白点深度. 但是也可以不换根.类似平常换根的往上g,往下f的拼凑 ...

  3. CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 好像这个题只能Dsu On Tree? 有根树点分治 统计子树过x的 ...

  4. AT3912 Antennas on Tree

    AT3912 Antennas on Tree %%zzt 只能考虑性质了. 把最后选择的k个点的连通块求出来,连通块内部的点表示都是互异的 连通块外部的点只能形成若干条链,并且这k个点的每一个最多与 ...

  5. CF1055F Tree and XOR

    CF1055F Tree and XOR 就是选择两个数找第k大对儿 第k大?二分+trie上验证 O(nlognlogn) 直接按位贪心 维护可能的决策点(a,b)表示可能答案的对儿在a和b的子树中 ...

  6. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  7. SAP CRM 树视图(TREE VIEW)

    树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...

  8. 无限分级和tree结构数据增删改【提供Demo下载】

    无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...

  9. 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...

随机推荐

  1. docker采用registry部署简易仓库

    解释:registry部署简易仓库,实现免密上传拉取镜像(解决不在一个容器里,也能够实现镜像拉取成功) 1.安装启动registry服务 docker pull registry docker run ...

  2. SQL实例_11Oracle基本操作

    前言导读 本章介绍了在正常使用Oracle数据库之前进行的常规操作 本章语句的运行需要子啊PLSQL软件中运行 本章导入导出语句需要在虚拟环境中直接运行 1 Oracle创建表空间和用户 --1 创建 ...

  3. JavaScript数组 几个常用方法

    前言 数组方法有太多了,本文记录一些本人容易记错的一些数组方法,用于巩固及复习. 后续会慢慢的将其他数组方法添加进来. 善用数组方法可以使数据处理变的优雅且简单. 那下面让我们开始吧: filter( ...

  4. GDP区域分布图的生成与对比(ArcPy实现)

    一.背景 各地区经济协调发展是保证国民经济健康持续稳定增长的关键.GDP是反映各地区经济发展状况的重要指标.科学准确分析各地区GDP空间分布特征,对制定有效措施,指导经济协调发展具有重要参考价值. 二 ...

  5. MyBatis概念和”安装“

    MyBatis概念 MyBatis的前身就是iBatis,本是apache的一个开源项目,2010年这个项目由apahce sofeware foundation 迁移到了google code,并且 ...

  6. 什么是Sprint计划?

    Sprint 计划是Scrum框架中的一个事件,团队将确定他们将在冲刺期间处理的产品积压项目,并讨论他们完成这些产品积压项目的初始计划. 团队可能会发现建立冲刺目标很有帮助,并以此为基础确定他们在冲刺 ...

  7. Flink sql 之 join 与 StreamPhysicalJoinRule (源码解析)

    源码分析基于flink1.14 Join是flink中最常用的操作之一,但是如果滥用的话会有很多的性能问题,了解一下Flink源码的实现原理是非常有必要的 本文的join主要是指flink sql的R ...

  8. [no code][scrum meeting] Alpha 13

    项目 内容 会议时间 2020-04-21 会议主题 OCR技术对接会议 会议时长 45min 参会人员 全体成员 $( "#cnblogs_post_body" ).catalo ...

  9. 2021.8.15考试总结[NOIP模拟40]

    T1 送花 线段树.枚举右端点,线段树记录左端点对应的值. 每次对当前颜色上上次出现的位置到上次出现的位置区间减,上次出现的位置到当前位置区间加. $code:$ 1 #include<bits ...

  10. 示波器分析I2C时序波形图

    对于嵌入式开发的朋友来说,I2C协议实在是再熟悉不过了,有太多的器件,采用的都是通过I2C来进行相应的设置.今天,我们就随便聊聊这个I2C协议. I2C协议中最重要的一点是I2C地址.这个地址有7位和 ...