「ARC103D」 Distance Sums

传送门

水题。

首先如果让你求树上的节点 \(i\) 到其它所有节点的距离和,这是非常简单的,这就是非常常规的换根 \(\texttt{DP}\)。

那么,我们可以观察一下这个答案的递推式:\(f_u=f_{fa_u}-siz_u+(n-siz_u)\)。

也就是说,如果我们确定了 \(f_u\),那么我们可以确定 \(f_{fa_u}\) 的值。

又根据递推式,我们可以考虑这样的一种构造方式:

首先将 \(f\) 从大到小排序,如果当前 \(f\) 值未被标记过,则令其为叶子节点,否则将其与对应节点连边。

然后根据递推式将 \(f_u-n+2siz_u\) 标记。

如此,如果不能建出 \(n-1\) 条边,那么肯定不存在合法解。

然后值得注意的几点:

  • 注意我们实际上只是保证了 \(f_{fa_u}-f_u\) 的差值符合题目要求,所以我们需要对我们建出的树任意求出某个点的 \(f\) 来检验正确性。
  • 在 \(f\) 中有两个最小值(即树有两个重心)时依据不同写法可能会有一些细节需要处理。(虽然数据没卡)

贴代码

/*---Author:HenryHuang---*/
/*---Never Settle---*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e5+5;
struct node{
ll d;ll id;
bool operator<(const node &h)const{
return d>h.d;
}
}p[maxn];
map<ll,int> mp;
ll cnt;
ll num[maxn];
vector<int> e[2*maxn];
vector<pair<int,int> >ans;
vector<int> g[maxn];
ll dis[maxn],siz[maxn];
void dfs(int u,int f){
siz[u]=1;
for(auto v:g[u]){
if(v==f) continue;
dfs(v,u);
siz[u]+=siz[v];
dis[u]+=dis[v]+siz[v];
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
ll n;cin>>n;
ll owo=0;
for(ll i=1;i<=n;++i){
ll x;cin>>x;
if(i==1) owo=x;
p[i]=(node){x,i};
}
sort(p+1,p+n+1);
for(ll i=1;i<=n;++i){
if(!mp.count(p[i].d)){
mp[p[i].d]=++cnt;
}
ll tmp=mp[p[i].d];
++num[p[i].id];
while(e[tmp].size()&&((p[i].d-n+2*(num[p[i].id]+num[e[tmp].back()])<=p[i].d)||i==n)){
ans.emplace_back(e[tmp].back(),p[i].id);
num[p[i].id]+=num[e[tmp].back()];
e[tmp].pop_back();
}
if(!mp.count(p[i].d-n+2*num[p[i].id])){
mp[p[i].d-n+2*num[p[i].id]]=++cnt;
}
tmp=mp[p[i].d-n+2*num[p[i].id]];
e[tmp].emplace_back(p[i].id);
}
for(auto [x,y]:ans) g[x].emplace_back(y),g[y].emplace_back(x);
dfs(1,0);
if((int)ans.size()!=n-1||dis[1]!=owo) cout<<-1<<'\n';
else
for(auto [x,y]:ans) cout<<x<<' '<<y<<'\n';
return 0;
}

「ARC103D」 Distance Sums的更多相关文章

  1. 「ARC103D」Robot Arms「构造」

    题意 给定\(n\)个点,你需要找到一个合适的\(m\)和\(d_1,d_2,...,d_m\),使得从原点出发每次向四个方向的某一个走\(d_i\)个单位,最终到达\((x_t, y_t)\).输出 ...

  2. Loj #3059. 「HNOI2019」序列

    Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...

  3. loj #2008. 「SCOI2015」小凸想跑步

    #2008. 「SCOI2015」小凸想跑步   题目描述 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 n nn 边形,N NN 个顶点按照逆时针从 0∼n−1 0 ...

  4. 「杂烩」精灵魔法(P1908逆序对弱化版)

    「杂烩」精灵魔法(P1908逆序对弱化版) 题面: 题目描述 \(Tristan\)解决了英灵殿的守卫安排后,便到达了静谧的精灵领地--\(Alfheim\) .由于$ Midgard$ 处在$ Al ...

  5. Python后端日常操作之在Django中「强行」使用MVVM设计模式

    扫盲 首先带大家了解一下什么是MVVM模式: 什么是MVVM?MVVM是Model-View-ViewModel的缩写. MVVM是MVC的增强版,实质上和MVC没有本质区别,只是代码的位置变动而已 ...

  6. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  7. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  8. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  9. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

随机推荐

  1. Docker学习(11) Dockerfile指令

    Dockerfile指令 指令格式 FROM MAINTAINER RUN EXPOSE CMD ENTRYPOINT ADD COPY VOLUME WORKDIR ENV USER ONBUILD ...

  2. sql server 操作(不定期更新)

    要求:基本的语法要清楚. sql server疑难点: 1.Partition by可以理解为 对多行数据分组后排序取每个产品的第一行数据 先处理内查询,由内向外处理,外层查询利用内层查询的结果嵌套查 ...

  3. java中存储mysql数据库时间类型【date、time、datetime、timestamp】

    在MySQL中对于时间的存储自己见表的时候都是设置的varchar类型的,感觉挺方便的. 昨天拿别人建好的表写代码,发现这张表中时间类型为datetime的,凭感觉试了一下不行,网上查了刚开始试了好几 ...

  4. 桥接PyTorch和TVM

    桥接PyTorch和TVM 人工智能最引人入胜的一些应用是自然语言处理.像BERT或GPT-2之类的模型及其变体,可以获住足够多的文本信息. 这些模型属于称为Transformers的神经网络类体系结 ...

  5. GPU上的基本线性代数

    GPU上的基本线性代数 cuBLAS库提供了基本线性代数子例程(BLAS)的GPU加速实现.cuBLAS通过针对NVIDIA GPU进行了高度优化的嵌入式行业标准BLAS API来加速AI和HPC应用 ...

  6. HarmonyOS系统概述

    HarmonyOS系统概述 系统定位 HarmonyOS是一款"面向未来".面向全场景(移动办公.运动健康.社交通信.媒体娱乐等)的分布式操作系统.在传统的单设备系统能力的基础上, ...

  7. VB 老旧版本维护系列---有点懵逼的webserver访问

    有点懵逼的webserver访问 '定义webserver地址 Dim postUrl As String = "" '定义webserver所需xml字符串参数 Dim xmlR ...

  8. Centos8配置Nginx开机自启动

    第一步:创建service文件,并编辑(可理解为开机时自动启动Nginx的脚本服务文件) vim /lib/systemd/system/nginx.service /lib 与 /usr/lib 里 ...

  9. 编译原理-一种词法分析器LEX原理

    1.将所有单词的正规集用正规式描述 2.用正规式到NFA的转换算 得到识别所有单词用NFA 3.用NFA到DFA的转换算法 得到识别所有单词用DFA 4.将DFA的状态转换函数表示成二维数组 并与DF ...

  10. Golang学习(用代码来学习) - 第五篇

    /** 并发控制:context的学习 */ func context_test() { PrintStartSeperator("context_test") ctx, canc ...