当前位置: 首页 > news >正文

【C++贪心】P10537 [APIO2024] 九月|普及+

本文涉及知识点

C++贪心

[APIO2024] 九月

题目背景

请勿使用 C++14(GCC9) 提交

杭州市的中心广场有一棵著名的古树。这棵古树可以看作一棵 NNN 个节点的有根树,节点编号从 000N−1N - 1N1,其中 000 号节点是根节点。

称没有孩子的节点为叶子节点。古树每次落叶时,会选择一个当前的叶子节点删去。每一天中,古树可能会多次落叶。

MMM 位志愿者(编号从 000M−1M - 1M1)负责看护古树。每一位志愿者将各自按照如下方式独立记录今年的落叶的情况:

每一天,收集所有新的落叶的编号(即当天删除的节点的编号),然后将它们按任意顺序写在先前的落叶编号之后。

例如:第一天,叶子 333444 落下,于是他们写下 3,43, 43,44,34, 34,3。第二天,叶子 111222 落下,于是他们继续写下 1,21, 21,22,12, 12,1。最终的记录可能为 (3,4,1,2)(3, 4, 1, 2)(3,4,1,2)(4,3,1,2)(4, 3, 1, 2)(4,3,1,2)(3,4,2,1)(3, 4, 2, 1)(3,4,2,1)(4,3,2,1)(4, 3, 2, 1)(4,3,2,1) 中的任意一个。

这个过程持续了 KKK 天,每天都有新的叶子掉落,直到只剩根节点为止。

你在旅途过程中经过了杭州。此刻已是寒冬,仰望古树光秃秃的枝干,你不禁想起落叶纷飞的美丽景象。

你很想知道今年有几天能看见落叶,但你只能找到 MMM 位志愿者的记录。尝试根据这些记录推断出 KKK 可能的最大值。

题目描述

你无需在程序开头引入库 september.h

你只需要实现以下函数:

int solve(int N, int M, std::vector<int> F,std::vector<std::vector<int>> S);
  • NNN:古树的节点数量。
  • MMM:志愿者的数量。
  • FFF:一个长度为 NNN 的数组。对于 1≤i≤N−11 \le i \le N - 11iN1F[i]F[i]F[i] 表示节点 iii 的父亲节点的编号。F[0]F[0]F[0] 始终为 −1-11
  • SSS:一个长度为 MMM 的数组。SSS 中的每个元素是一个长度为 N−1N - 1N1 的数组。S[i][j]S[i][j]S[i][j] 表示志愿者 iii 记录的第 jjj 个节点编号(从 000 开始)。
  • 该函数必须返回一个整数,表示根据如上规则的 KKK 可能的最大值(即,最大可能的落叶天数)。
  • 对于每个测试点,交互库可能调用该函数多于一次。每次调用都应该作为新的情况分别处理。

注意:由于函数调用可能会发生多次,选手需要注意之前调用的残余数据对于后续调用的影响,尤其是全局变量的状态。

输入格式

评测程序示例读取如下格式的输入:

  • 第 1 行:TTT

对于接下来 TTT 组数据中的每一组:

  • 111 行:NMN\ MN M
  • 222 行:F[1]F[2]…F[N−1]F[1]\ F[2]\ \ldots\ F[N - 1]F[1] F[2]  F[N1]
  • 3+i(0≤i≤M−1)3 + i\ (0 \le i \le M - 1)3+i (0iM1) 行:S[i][0]S[i][1]S[i][2]…S[i][N−2]S[i][0]\ S[i][1]\ S[i][2]\ \ldots\ S[i][N - 2]S[i][0] S[i][1] S[i][2]  S[i][N2]

输出格式

评测程序示例按照如下格式打印你的答案:

对于每组测试数据:

  • 第 1 行:函数 solve 的返回值

样例 #1

样例输入 #1

1
3 1
0 0
1 2

样例输出 #1

2

样例 #2

样例输入 #2

1
5 2
0 0 1 1 
1 2 3 4
4 1 2 3

样例输出 #2

1

提示

样例解释

对于样例一,考虑如下调用:

solve(3, 1, {-1, 0, 0}, {{1, 2}});

对应的树如下图所示:

叶子 111222 可能在同一天落下,或者叶子 111 在第一天先落下,然后叶子 222 在第二天落下。落叶天数不超过 222

因此,程序应当返回 222

对于样例二,考虑如下调用:

solve(5, 2, {-1, 0, 0, 1, 1}, {{1, 2, 3, 4}, {4, 1, 2, 3}});

对应的树如下图所示:

假设至少有 222 天落叶,根据志愿者的记录,叶子 444 将在不同的日子(第一天和最后一天)落下,这是矛盾的。

因此,程序应当返回 111

数据范围

  • 2≤N≤1052 \le N \le 10^52N105
  • 1≤M≤51 \le M \le 51M5
  • ∑NM≤8×105\sum NM \le 8 \times 10^5NM8×105
  • F[0]=−1F[0] = -1F[0]=1 且对于 1≤i≤N−11 \le i \le N - 11iN1, 0≤F[i]≤i−10 \le F[i] \le i - 10F[i]i1
  • 对于 1≤i≤M−11 \le i \le M - 11iM1, 数组 S[i]S[i]S[i] 是一个 1,2,…,N−11, 2, \ldots , N - 11,2,,N1 的排列
  • 保证 FFF 描述的是一棵以节点 000 为根的有根树

详细子任务附加限制及分值如下表所示。

子任务编号附加限制分值
1M=1,N≤10,∑N≤30M=1,N\le 10,\sum N\le 30M=1,N10,N30111111
2N≤10,∑N≤30N\le 10,\sum N\le 30N10,N30141414
3M=1,N≤1000,∑N≤2000,F[i]=i−1M=1,N\le 1\,000,\sum N\le 2\,000,F[i]=i-1M=1,N1000,N2000,F[i]=i1555
4M=1,N≤1000,∑N≤2000M=1,N\le 1\,000,\sum N\le 2\,000M=1,N1000,N2000999
5N≤1000,∑N≤2000,F[i]=i−1N\le 1\,000,\sum N\le 2\,000,F[i]=i-1N1000,N2000,F[i]=i1555
6N≤1000,∑N≤2000N\le 1\,000,\sum N\le 2\,000N1000,N2000111111
7M=1,F[i]=i−1M=1,F[i]=i-1M=1,F[i]=i1999
8M=1M=1M=1111111
9F[i]=i−1F[i]=i-1F[i]=i1999
10没有额外的约束条件161616

贪心

依次处理各天的落叶。
令第i天,令之前已经记录j项记录。
unorder_set 将各记录员的第j项记录加到s中。j++
但 j < s.size()时 将各记录员的第j项记录加到s中。j++
如果某叶子掉了,那么它的子孙一定在当天之前掉落了。但一个叶子掉落,将没有掉落的子叶子记录到wait中。从wait中取当前叶子。

原理

假如第[0,i]天共有j片落叶,则所有记录前j项记录的落叶,排序后一定相同。

代码

核心代码

	#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>#include <bitset>
using namespace std;int solve(int N, int M, std::vector<int> F,	std::vector<std::vector<int>> S) {vector<vector<int>> child(N);for (int i = 1; i  < N; i++) {	child[F[i]].emplace_back(i );}int ans = 0;unordered_set<int> s,wait;for (int i = 0; i+1 < N ; ) {ans++;do {for (const auto& v : S) {if (s.count(v[i])) { continue; }s.emplace(v[i]);for (const auto& c : child[v[i]]) {if (s.count(c)) { continue; }wait.emplace(c);}wait.erase(v[i]);}i++;}while((s.size() != i)|| wait.size());}return ans;}

单元测试

int N, M;std::vector<int> F;std::vector<std::vector<int>> S;TEST_METHOD(TestMethod11){N = 3, M = 1, F = { -1,0,0 }, S = { { 1,2} };auto res = solve(N, M, F, S);AssertEx(2, res);}TEST_METHOD(TestMethod12){N = 5, M = 2, F = {-1, 0, 0, 1, 1 }, S = { { 1, 2, 3, 4},{4 ,1 ,2, 3} };auto res = solve(N, M, F, S);AssertEx(1, res);}TEST_METHOD(TestMethod13){N = 3, M = 1, F = { -1,0,1 }, S = { { 1,2} };auto res = solve(N, M, F, S);AssertEx(1, res);}

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

http://www.dtcms.com/a/461758.html

相关文章:

  • 大模型问答原理解析
  • 【二叉树的递归算法与层序遍历算法】
  • 【STM32】I2C通信—软件模拟
  • 公司网站怎么修改内容wordpress 4.7.2 中文
  • 怎么建手机网站seo新方法
  • 第六章 QT和OPENCV交叉编译开发环境以及QT远程调试
  • hello_mybatis
  • 【大模型理论篇】MCP协议中sse、stdio、streamable_http含义
  • Git 小白超详细指南
  • 深度学习基础:从原理到实践——第二章神经网络(上)
  • 企业网站制作报价单哈尔滨视频剪辑培训机构
  • SOME/IP车载服务的形式化安全分析和防护
  • TCP三次握手与四次挥手状态解析
  • 网站想换空间invoker wordpress
  • Eureka注册中心
  • 网站建设销售总结房屋装修在线设计网站
  • 机器学习基本概念
  • Buffer:Node.js 里处理二进制数据的 “小工具”
  • 网站开发博客大前端d8扁平化wordpress模板
  • Go 语言环境安装指南
  • UiPath2025笔记第六节:java调试API触发器
  • Python实现自动化巡检ESXi6.7并输出excel报告
  • wordpress手机显示不了图片关键词优化计划
  • Python学习之基础篇
  • 手机app开发 网站建设描述网站开发的广告词
  • 24届-Python面经(华为OD)
  • JavaSpring项目之连接,并使用redis
  • 前端核心框架vue之(vue状态核心案例篇4/5)
  • 前端请求优化进阶:并发控制、缓存优化与错误重试实战教程
  • 网站建设的主要特征一个网址需要多少钱