P13643 Guess

题目背景

猜猜我是谁?

题目描述

### 本题仅允许使用 C++ 语言提交。 小 Q 有一个长度为 $n$ 的隐藏排列 $p$,你要把它猜出来。 你可以问他两个位置上较大的那个值是多少,你也可以问他一个答案是否正确,他会诚实的回答你。 ### 实现细节 你需要在代码开头加入如下代码: ```cpp #include int _max(int x,int y); bool _ask(std::vector a); ``` 你要实现以下函数: ```cpp std::vector Guess(int n) ``` - 保证在每个测试点交互库恰好调用 **$50$** 次该函数,且在一个测试点内 $n$ 的值相同。 - $n$ 表示排列 $p$ 的长度。 - 该函数应该返回一个数组 `Ans`,下标从 $0$ 开始,表示你猜测的排列 $p$。 上述函数可以调用如下两个函数: ```cpp int _max(int x,int y) ``` - $x,y$ 表示你询问的位置,你需要保证 $1\leq x,y\leq n,x\not=y$。 - 该函数会返回 $\max(p_x,p_y)$。 - 对每一次 `Guess` 函数的调用,该函数最多被调用 $10^5$ 次。 ```cpp bool _ask(std::vector a) ``` - 数组 $a$ 表示你询问的排列,下标从 $0$ 开始,你需要保证 $a$ 是一个 $1-n$ 的排列。 - 若你的排列 $a$ 与答案排列 $p$ 相同,该函数会返回 True,否则返回 False。 - 对每一次 `Guess` 函数的调用,该函数最多被调用 $10$ 次。 **本题的目的是使得 `_ask` 函数和 `_max` 函数的总调用次数尽量少。每一个测试点都有一个满分线 $MAX$,评测程序根据 $MAX$ 和你的总调用次数来评分。** **评测程序的行为是非自适应的。这意味着在每次调用 `Guess` 前,排列 $p$ 是固定的。**

输入格式

第一行两个整数 $n,T$,表示排列长度和 `Guess` 函数被调用的次数,保证 $1\leq n\leq10^4$,在数据中,保证 $T=50$(在样例中不保证)。 接下来 $T$ 行,每行有 $n$ 个整数,表示每次调用中隐藏的排列 $p$,保证每行的 $n$ 个整数组成一个 $1-n$ 排列。

输出格式

共 $T$ 行,每行输出该次测试的结果。 若你的所有调用合法,并且返回的排列正确,则输出 `Y` 与你的函数调用两个函数的次数。 否则输出一个字符 `N`。

说明/提示

**【样例解释】** 对于样例 $1$,可能的调用顺序: | 选手程序 | 交互库 | 说明 | | :-----------: | :-----------: |:-----------: | | | 获得排列,如 $[1,3,2]$ | | | | 调用 `Guess(3)` | 开始测试 | | 调用`_max(1,2)` | 返回 $3$ | $\max(p_1,p_2)=\max(1,3)=3$ | | 调用`_ask([1,3,2])` | 返回 True | 猜测排列与真实排列相同 | | 运行结束并返回 $[1,3,2]$ | 向屏幕打印交互结果、`_max`和`_ask`的调用次数:`Y 1 1` | 交互结束,结果正确,次数小于满分标准 | **【数据范围】** 对于所有数据保证:$p$ 为 $1-n$ 的排列,$1\leq n\leq 10^4$。 本题共有 $50$ 组测试点,每个测试点的分值均为 $100$ 分,得分为所有测试点得分的平均数,数据范围如下: 设 $c$ 为测试点编号, - 对于测试点 $1-5$:$n=c$ - 对于测试点 $6-10$:$n=2c$ - 对于测试点 $11-20$:$n=5c$ - 对于测试点 $21-30$:$n=50c$ - 对于测试点 $31-50$:$n=200c$ **【评分方式】** 注意: - 选手不应通过非法方式获取交互库里的信息,如试图读取排列 $p$ 的值,或直接与标准输入、输出流进行交互。此类行为将被视为作弊。 在每次 `Guess` 函数的调用中,程序调用 `_max` 次数不得超过 $10^5$ 次,`_ask` 次数不得超过 $10$ 次,否则将会获得 $0$ 分。 若你调用 `_max` 或 `_ask` 的参数不符合题目要求,或者 `Guess` 的返回值不符合题目要求,将会获得 $0$ 分并获得 `Wrong function using` 的返回。 若你的返回值与正确排列 $p$ 不同,将会获得 $0$ 分并获得 `Wrong answer permutation` 的返回。 我们设你调用 `_max` 和 `_ask` 的总次数在 $T$ 次 `Guess` 函数调用中的最大值为 $w$,满分标准(满分标准见附件)为 $MAX$,若你返回正确排列,评分方式如下: | $w$ | 分数系数 | | :----------: | :----------: | | $[0,MAX]$ | $1$ | | $(MAX,2n)$ | $1-0.8(\log_{2n-MAX}w-MAX)$ | | $[2n,10^5+10]$ | $0.2$ | **【本地测试】** 可以在代码最后加入以下示例交互库,按照输入格式测试。 示例交互库并**不判断**你的函数调用合法性,所以请注意你是否合法调用。 ```cpp #include using namespace std; vector Guess(int n); int __p[10005],__n,__T,__cnt1,__cnt2; int _max(int x,int y){ ++__cnt1; return max(__p[x],__p[y]); } bool _ask(vector a){ ++__cnt2; for(int i=0;i>__n>>__T; for(int i=1;i