luogu#P8150. 再会 | Sayounara
再会 | Sayounara
题目背景
「过去的都已经无所谓了吗?」
“还没有达到那种地步。”
「想做的事都已经完成了吗?」
“如今的自己,也好像只能在取舍中前行。”
「道过再会了吗?」
“… 还没有,但我正尝试着。”
I have
我仍有
plenty want to say
无数未道尽的言语
Before
在离开之前
I leave this world
在再会之前
题目描述
「这是…?」
“啊… 我自己写的日记管理程序。”
「噗… ‘正常人谁写日记啊’,平时的你应该会这样说吧?」
“… 别拿我说笑。”
「好吧好吧。不过看上去你不记得密码了呢?」
“…… 我自有手段。”
「咦…?这什么,恢复软件吗?」
“嗯… 密码可以被表示为一个长为 的非负整数序列,其中每个元素都互不相同 。这个软件可以执行两种操作:一是,询问一个连续区间的总和减去这个区间最小值的结果;二是,询问一个位置的值。现在我需要找回密码的话…”
「欸?为什么不直接用 次第二种操作呢?」
“这是试用版… 所以第二种操作只有两次使用的体验权限… 而且第一种操作似乎也有一定的限制,所以…”
「这… 话说为什么恢复个密码这么麻烦啊?不应该会有‘找回密码’之类方便的机制吗?」
“… 多半还是那个人的安排吧。”
简要题意
有一个元素互不相同的非负整数序列 ,其长度为 。你可以多次进行以下两种询问之一:
-
给出 ,得到 $\left(\sum_{k=l}^r a_k\right)-\left(\min_{k=l}^r a_k\right)$。
-
给出 ,得到 的值。这种询问最多只能进行两次。
你需要在尽可能少的询问次数内推断出该序列的内容。
本题询问均以 为初始下标,但你返回答案时需要返回以 为初始下标的 vector
,请留意。
交互说明
本题仅限 C++11 / C++17 提交。你需要实现以下的函数:
#include <cstdint>
#include <vector>
std::vector<uint32_t> recover(int n);
该函数接收密码长度 ,返回还原的密码(返回值应该是一个大小为 的 vector
)。你可以使用以下两个函数
#include <cstdint>
uint64_t query(int l, int r);
uint32_t get(int x);
其中 query
对应题目中的第一种操作,get
对应题目中的第二种操作。
下面是一个示例程序(仅演示交互库操作):
#include <cstdint>
#include <vector>
uint64_t query(int l, int r);
uint32_t get(int x);
std::vector<uint32_t> recover(int n) {
std::vector<uint32_t> ans(n);
int what = query(1, n), hey = get(1);
for (int i = 0; i < n; ++i) ans[i] = i + 1;
return ans;
}
题目提供了示例交互库 lib.cpp
(并非交互库真实实现)。你可以在本地使用命令 g++ -o code code.cpp lib.cpp
来编译运行。
输入格式
这是交互库的输入格式,选手不需要,也无法从标准输入中读取任何信息。
第一行,一个正整数 表示密码长度。
第二行, 个非负整数表示密码。
输出格式
这是交互库的输出格式,选手不需要,也无法向标准输出中写入任何信息。
输出有四种:
-
0 A B
:选手答案正确。其中A
代表操作一的使用次数,B
代表操作二的使用次数。 -
-1
:选手函数成功执行,但答案不正确。 -
-2
:选手在调用操作一时传入的 不满足要求。 -
-3
:选手调用了超过 次操作一。 -
-4
:选手调用了超过两次操作二。
提示
得分细则
本题没有子任务。所有测试点保证 。
如果你在任何一个测试点中答案错误或超出询问限制,则本题你会得到 0 分的好成绩。
如果你成功通过了所有测试点,记你在所有数据中调用操作一最多一次的次数为 ,则你本题的分数为:
$$\begin{cases} \frac{60}{e^7-1}\left(e^{10-\max\left\{\frac{x-10^6}{100},3\right\}}-1\right)+40,&x\le 1001000\\ 25,&\mathrm{otherwise.} \end{cases} $$