[ARC117D]Miracle Tree
将$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的更多相关文章
- Atcoder Regular Contest 117 D - Miracle Tree(分析性质+构造)
Atcoder 题面传送门 笑死,阴间语文作业到现在还没写完,为了在这个点保持精神,我只好来颓篇题解辣 我们考虑探究一下怎么最小化 \(\max\limits_{i=1}^nE_i\),我们假设 \( ...
- QTREE5 - Query on a tree V——LCT
QTREE5 - Query on a tree V 动态点分治和动态边分治用Qtree4的做法即可. LCT: 换根后,求子树最浅的白点深度. 但是也可以不换根.类似平常换根的往上g,往下f的拼凑 ...
- 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的 ...
- AT3912 Antennas on Tree
AT3912 Antennas on Tree %%zzt 只能考虑性质了. 把最后选择的k个点的连通块求出来,连通块内部的点表示都是互异的 连通块外部的点只能形成若干条链,并且这k个点的每一个最多与 ...
- CF1055F Tree and XOR
CF1055F Tree and XOR 就是选择两个数找第k大对儿 第k大?二分+trie上验证 O(nlognlogn) 直接按位贪心 维护可能的决策点(a,b)表示可能答案的对儿在a和b的子树中 ...
- [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法
二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...
- SAP CRM 树视图(TREE VIEW)
树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...
- 无限分级和tree结构数据增删改【提供Demo下载】
无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...
- 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...
随机推荐
- 随机生成文章的AI(C++)
#include <iostream> #include <cstdlib> #include <ctime> #include <fstream> u ...
- scratch塔罗牌的制作
首先,这个程序的流程是洗牌->占卜,很简单的一个程序.那个程序的组成是什么呢? 该程序由22张大卡.开始洗牌按钮.占卜按钮和说出占卜结果的角色组成. 先来说说开始洗牌按钮吧. 开始的时候移动到相 ...
- 树莓派4B学习札记
防静电 树莓派比较容易被静电损坏,要做好以下预防措施 使用的时候不要用手去触摸PCB和针脚!特别是上电之后! 拿板卡的时候,要习惯性拿板卡的边缘 勤洗手,勤摸墙壁,释放身上的静电 系统安装 8GB以上 ...
- Netty学习笔记(2)ByteBuffer
1. 测试ByteBuffer 1.1 依赖 <dependencies> <dependency> <groupId>io.netty</groupId&g ...
- OO第四单元UML作业总结暨OO课程总结
目录 目录一.第四单元UML两次作业架构设计第一次作业第二次作业二.架构设计总结与OO方法理解演进三.测试理解与实践演进四.课程收获总结五.课程改进建议六.尾声 一.第四单元UML两次作业架构设计 第 ...
- OO_JAVA_表达式求导_单元总结
OO_JAVA_表达式求导_单元总结 这里引用个链接,是我写的另一份博客,讲的是设计层面的问题,下面主要是对自己代码的单元总结. 程序分析 (1)基于度量来分析自己的程序结构 第一次作业 程序结构大致 ...
- 这一篇 K8S(Kubernetes)我觉得可以了解一下!!!
点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 什么是Kubernetes? Kubernetes 是Google开源的分布式容器管理平台,是为 ...
- 『学了就忘』Linux基础 — 4、VMware安装
目录 1.VMware介绍 2.VMware主要特点 3.VMware建议配置 4.VMware安装 1.VMware介绍 VMware是一个虚拟PC的软件,可以在现有的操作系统上虚拟出一个新的硬件环 ...
- windows下安装dirmap详细教程
今天安装一下dirmap,纯小白非常详细的安装过程 1.先去下载dirmap 下载地址:https://github.com/H4ckForJob/dirmap 点这个绿色的code,然后再点下面这个 ...
- vim 让人爱不释手的编辑器之神
VIM 基本介绍 vim诞生已有20多年,它常被人称之为编辑器之神,vim的操作理念可以说是独具一格而又出类拔萃,使用vim能极大的提升文本处理效率,因此熟练掌握vim应该是每个程序员都应该做到的事情 ...