P10678 『STA - R6』月 题解

news/2024/10/6 9:13:15

Solution

看了别的大佬的题解,感觉都是数学证明然后用树和图做的,看不懂啊。。。萌新瑟瑟发抖

用 vector 模拟树,然后贪心摸索做出来了。注意到要求最深叶子结点和最浅叶子结点的距离最短时的情况,那么此时根节点应该是树中度数最大的点,把树尽可能的拓宽,深度换宽度。

那么同理的根节点的子树的根节点应该也是该子树中度数最深的点,那么可得出该树应该是类似一个大根堆(出度不一定为 \(2\),因此类似),且每层的数量其实是固定的(由上一层的度数之和决定,而根节点又确定),因此仅通过一次排序,便可得到由根节点到最后一个叶子结点,每层的顺序:

如:样例第四

7
1 3 2 3 1 1 1

通过结构体将每个元素的度数和原次序绑定,得如下顺序:
(后期要改度数用出度,将除了根节点之外的度数均减一)

//表格一
4
2
1 1&&&
1 2   //原次序
1 1   //度数
&&&3
1 1 2&&&
3 1 2
2 1 1
&&&5
1 1 2 2 2&&&
3 4 5 1 2
2 2 2 1 1
&&&7
1 3 2 3 1 1 1&&&
2 4 3 1 5 6 7
3 3 2 1 1 1 1
&&&

然后再将 "&&" 中的结构体装进 vector 里面模拟树(仅是因为 vector 方便打,其实用树结构体存效果一样):

//表格二
4
2
1 1&&&1 &&&  //树中存的是节点的次序
&&&2 &&&&&&1 &&&  //树中存的是节点的出度
&&&0 &&&
3
1 1 2
&&&3 &&&
&&&1 2 &&&&&&2 &&&
&&&0 0 &&&
5
1 1 2 2 2
&&&3 &&&
&&&4 5 &&&
&&&1 2 &&&&&&2 &&&
&&&1 1 &&&
&&&0 0 &&&
7
1 3 2 3 1 1 1
&&&2 &&&
&&&4 3 1 &&&
&&&5 6 7 &&&&&&3 &&&
&&&2 1 0 &&&
&&&0 0 0 &&&

“&”“&” 中的是 vector 数组中每层的情况,(除了根节点之外的节点度数减了 \(1\),转变成出度)。而决定该层数是由上一层的所有点的出度之和(第二层根据根节点的出度)。下一层中的任何一个都可做上一层节点的孩子,不影响树的最深最浅叶子结点层数。


最后把树的情况输出来即可:

如最后一例:

&&&2 &&&         //节点次序
&&&4 3 1 &&&
&&&5 6 7 &&&&&&3 &&&         //3->2,3->1,3->0
&&&2 1 0 &&&     //2->0,2->0,2->0
&&&0 0 0 &&&     //父节点领养子节点情况

//将上面的诸如 \(2\),\(0\) 之类转成\(↑\)上面树中存的节点次序输出来即可变成:

树

Code

#include <bits/stdc++.h>
using namespace std;
#define to(x,y); for(int x=1;x<=y;x++)
#define fr(x,y); for(int x=0;x<y;x++)
const int N = 2e5 + 20;
int t, n, sum[N];struct nd {int ord, cry;
} p[N];
vector<nd> tr[N];bool cmp(nd a, nd b) {if (a.cry == b.cry)return a.ord < b.ord;return a.cry > b.cry;
}int main() {scanf("%d", &t);while (t--) {scanf("%d", &n);to(i, n)scanf("%d", &p[i].cry), p[i].ord = i;sort(p + 1, p + 1 + n, cmp);to(i, n) {if (i > 1)p[i].cry--;sum[i] = sum[i - 1] + p[i].cry;}int l = 1, r = 1, num, dep = 1;tr[1].push_back({p[1].ord, p[1].cry});while (r < n) {dep++;num = sum[r] - sum[l - 1];l = r + 1, r = r + num;for (int i = l; i <= r; i++)tr[dep].push_back({p[i].ord, p[i].cry});}to(i, dep - 1) {int len = tr[i].size(), idx = 0;fr(j, len) {for (int k = 0; k < tr[i][j].cry; k++) {printf("%d %d\n", tr[i][j].ord, tr[i + 1][idx + k]);}idx += tr[i][j].cry;}}to(i, dep)vector <nd>().swap(tr[i]);}return 0;
}

附带表格可视化并附解释

#include <bits/stdc++.h>
using namespace std;
#define to(x,y); for(int x=1;x<=y;x++) //丑陋的代码化简习惯
#define fr(x,y); for(int x=0;x<y;x++)
const int N = 2e5 + 20;
int t, n, sum[N];// sum 为出度前缀和,求每层的节点数
struct nd {int ord, cry;
} p[N];          //存输入数据并做预处理用
vector<nd> tr[N];//核心 vector 树bool cmp(nd a, nd b) {if (a.cry == b.cry)return a.ord < b.ord;return a.cry > b.cry;
}//排序预处理int main() {scanf("%d", &t);while (t--) {scanf("%d", &n);
//		memset(p, 0, sizeof p); //无用的初始化to(i, n)scanf("%d", &p[i].cry), p[i].ord = i;sort(p + 1, p + 1 + n, cmp);/*表格一*/
//		puts("\n&&&");
//		to(i, n)printf("%d ", p[i].ord);
//		puts("");
//		to(i, n)printf("%d ", p[i].cry);
//		puts("\n&&&\n");to(i, n) {if (i > 1)p[i].cry--;//改度数为出度sum[i] = sum[i - 1] + p[i].cry;//前缀和}int l = 1, r = 1, num, dep = 1;tr[1].push_back({p[1].ord, p[1].cry});//存下根节点while (r < n) {dep++;//由上一层来到下一层num = sum[r] - sum[l - 1];//上层度数之和l = r + 1, r = r + num;for (int i = l; i <= r; i++)//“领养”子节点tr[dep].push_back({p[i].ord, p[i].cry});//存下该层子节点}/*表格二*/
//		to(i, dep) {
//			printf("&&&");
//			int len = tr[i].size();
//			fr(j, len)printf("%d ", tr[i][j].ord);
//			puts("&&&");
//		}
//		puts("");
//		to(i, dep) {
//			printf("&&&");
//			int len = tr[i].size();
//			fr(j, len)printf("%d ", tr[i][j].cry);
//			puts("&&&");
//		}to(i, dep - 1) {int len = tr[i].size(), idx = 0;// idx 为领养子节点的次序fr(j, len) {for (int k = 0; k < tr[i][j].cry; k++) {printf("%d %d\n", tr[i][j].ord, tr[i + 1][idx + k]);}//输出父子idx += tr[i][j].cry;//领下一批子节点}}to(i, dep)vector <nd>().swap(tr[i]);//清空 vector 树}//完结撒花return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/68247.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

学期(如2024-2025-1) 20241304 《计算机基础与程序设计》第2周学习总结

学期(如2024-2025-1)20241304 《计算机基础与程序设计》第2周学习总结 作业信息这个作业属于哪个课程 <班级的链接>(2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 <作业要求的链接>(如2024-2025-1计算机基础与程序设计第二周作业)这个作业的目标 <…

Cisco Firepower 1000 Series FTD Software 7.6.0 ASA Software 9.22.1

Cisco Firepower 1000 Series FTD Software 7.6.0 & ASA Software 9.22.1Cisco Firepower 1000 Series FTD Software 7.6.0 & ASA Software 9.22.1 Firepower Threat Defense (FTD) Software - 思科防火墙系统软件 请访问原文链接:https://sysin.org/blog/cisco-firep…

从零开始学机器学习——网络应用

首先给大家介绍一个很好用的学习地址:https://cloudstudio.net/columns 今天,我们的主要任务是按照既定的流程再次运行模型,并将其成功加载到 Web 应用程序中,以便通过 Web 界面进行调用。最终生成的模型将能够基于 UFO 目击事件的数据和经纬度信息,推断出事件发生的城市地…

Cisco Firepower 4100 Series FTD Software 7.6.0 ASA Software 9.22.1

Cisco Firepower 4100 Series FTD Software 7.6.0 & ASA Software 9.22.1Cisco Firepower 4100 Series FTD Software 7.6.0 & ASA Software 9.22.1 Firepower Threat Defense (FTD) Software - 思科防火墙系统软件 请访问原文链接:https://sysin.org/blog/cisco-firep…

Cisco Firepower 9300 Series FTD Software 7.6.0 ASA Software 9.22.1

Cisco Firepower 9300 Series FTD Software 7.6.0 & ASA Software 9.22.1Cisco Firepower 9300 Series FTD Software 7.6.0 & ASA Software 9.22.1 Firepower Threat Defense (FTD) Software - 思科防火墙系统软件 请访问原文链接:https://sysin.org/blog/cisco-firep…

读数据湖仓08数据架构的演化

读数据湖仓08数据架构的演化1. 数据目录 1.1. 需要将分析基础设施放置在数据目录(Data Catalogue)的结构中1.1.1. 元数据1.1.2. 数据模型1.1.3. 本体1.1.4. 分类标准1.2. 数据目录类似于图书馆的图书检索目录1.2.1. 先通过图书馆的图书检索目录进行查找,以便快速找到所需的图书…

VUE2常见问题以及解决方案汇总,vue+element ui 问题以及解决方案汇总(不断更新中)

解决vue项目中 el-table 的 @row-click 事件与行内点击事件冲突,点击事件不生效(表格行点击事件和行内元素点击事件冲突)需要阻止事件冒泡 问题描述 1.点击列的编辑按钮,会触发按钮本身事件,同时会触发行点击事件 2.点击列的元素,会触发本身事件,同时会触发行点击事件 需…

1分钟了解什么是docker和docker-compose?前后端必知必会技能GET啦

@目录前情提要Docker定义:主要功能:命令示例:其他Docker Compose定义:我为什么使用它?主要功能:命令示例:主要区别配置文件:命令行操作:依赖关系管理:实际应用场景单个服务:多服务应用:总结结语欢迎路过的小哥哥小姐姐们提出更好的意见哇~~ 前情提要 本文非常简短,如果需要详…