0%

2026牛客暑期多校 7——Problem D. 天下第一武道会(要多手摸样例啊,然后猜测一些结论啊,想一想样例为什么做出这样的选择)(不想要卡死=尽量晚卡死啊 / 所谓的让区间最大,就是找到最大的右端点)

题目大意

这是一份为您整理好的整洁、规范的中文题面,去除了杂乱的内容且未包含任何解题思路:

题目描述:天下一武道会 (Tenkaichi Budōkai)

时间限制: C/C++/Rust/Pascal 1秒,其他语言2秒

空间限制: C/C++/Rust/Pascal 1024 MB,其他语言2048 MB

特殊判定 (Special Judge): 是,64位整数输入输出格式:%lld

天下一武道会汇聚了来自世界各地的 nn 名武术家。武术家们的编号为 1,2,,n1, 2, \ldots, n

在比赛开始前,两名官员分别提交了固定的优先级列表 PPQQ。每个列表都恰好包含每位武术家一次,尽管武术家在两个列表中的排列顺序可能不同。

初始时,列表为:

P=(p1,p2,,pn)P = (p_1, p_2, \ldots, p_n)

Q=(q1,q2,,qn)Q = (q_1, q_2, \ldots, q_n)

其中这两个序列都是 1,2,,n1, 2, \ldots, n 的排列。一旦提交,两个列表的顺序都不允许被重新排列。

比赛委员会使用以下规则来模拟比赛。只要至少还有两名武术家剩余,就可以进行一场比赛:

uuvv 分别为当前列表 PPQQ 中排在最前面的未被淘汰的武术家。

  • 如果 u=vu = v,说明两位官员提名了同一位武术家。由于武术家不能与自己对战,且任何一位官员都不能跳过他们列表中的第一位武术家,此时模拟过程将陷入停滞状态,无法继续进行后续比赛。

  • 否则(即 uvu \neq v),uuvv 将进行对决。在模拟中,可以从 {u,v}\{u, v\} 中任意选择一名武术家 zz 作为败者。武术家 zz 将被淘汰出局,他也会同时从 PPQQ 两个列表中被移除。移除后,每个列表中剩余武术家的相对顺序保持不变。

经过恰好 n1n-1 场成功的比赛后,最终将只剩下一名武术家。这名武术家将被宣布为天下一武道会的冠军。

现在,你支持武术家 xx。请判断:是否存在一种合法的比赛胜负序列,使得整个模拟过程永远不会陷入停滞状态,并且武术家 xx 最终成为冠军?

如果存在这样的序列,请输出任意一个符合条件的被淘汰武术家序列。

输入格式

第一行包含两个整数 nnxx2n2×1052 \le n \le 2\times 10^51xn1 \le x \le n),分别表示武术家的数量和你希望成为冠军的武术家编号。

第二行包含 nn 个整数 p1,p2,,pnp_1, p_2, \ldots, p_n。保证序列 PP1,2,,n1, 2, \ldots, n 的一个排列。

第三行包含 nn 个整数 q1,q2,,qnq_1, q_2, \ldots, q_n。保证序列 QQ1,2,,n1, 2, \ldots, n 的一个排列。

输出格式

如果在不陷入停滞状态的前提下,无法使武术家 xx 成为冠军,请输出一行 NO

否则,第一行输出 YES

第二行输出 n1n-1 个整数 z1,z2,,zn1z_1, z_2, \ldots, z_{n-1},其中 ziz_i 表示在第 ii 场比赛中被淘汰的武术家。

注意:

在进行第 ii 场比赛前,设 uiu_iviv_i 分别为 PPQQ 中剩余排在最前面的武术家。你的输出必须满足 uiviu_i \neq v_izi{ui,vi}z_i \in \{u_i, v_i\}。在执行完全部的 n1n-1 场淘汰操作后,剩余的唯一武术家必须是 xx

如果存在多个符合条件的淘汰序列,输出其中任意一个均视为正确。

样例

样例 1

输入:

Plaintext

1
2
3
3 3
2 3 1
3 1 2

输出:

Plaintext

1
NO

样例 2

输入:

Plaintext

1
2
3
3 1
2 1 3
3 2 1

输出:

Plaintext

1
2
YES
2 3

样例 3

输入:

Plaintext

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

输出:

Plaintext

1
2
YES
4 3 2 5

样例解释

下面是对 样例 3 输出的详细解释:

初始时,PPQQ 中剩余排在最前面的武术家分别是 2 和 4。他们进行对决,武术家 4 被淘汰。列表更新为:

P=(2,3,1,5)P = (2, 3, 1, 5)

Q=(3,5,2,1)Q = (3, 5, 2, 1)

下一场比赛在武术家 2 和 3 之间进行。武术家 3 被淘汰,列表更新为:

P=(2,1,5)P = (2, 1, 5)

接下来,被提名的武术家是 2 和 5。武术家 2 被淘汰,此时:

P=(1,5)P = (1, 5)

Q=(5,1)Q = (5, 1)

最后,武术家 1 和 5 面对面进行对决,武术家 5 被淘汰。两个列表现在都只剩下武术家 1。

因此,模拟过程从未陷入停滞,武术家 1 成功成为了天下一武道会的冠军。

思路讲解

不想要卡死=尽量晚卡死啊

image

image

那么维护这样子的一个距离啊,可以使用这个 pbds。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

int choose_p_or_q() {
if (aliveP.empty() || aliveQ.empty()) {
return -1;
}
auto [pid,qid] = make_tuple(*aliveP.begin(), *aliveQ.begin());
ll pval = P[pid];
ll qval = Q[qid];
if (pval == qval) {
return -1;
}
ll disp = aliveQ.order_of_key(valToQPos[pval]);
ll disq = aliveP.order_of_key(valToPPos[qval]);
auto erase_q = [&]() {
++ans_idx;
Ans[ans_idx] = Q[qid];
aliveQ.erase(qid);
aliveP.erase(valToPPos[qval]);
};
auto erase_p = [&]() {
++ans_idx;
Ans[ans_idx] = P[pid];
aliveP.erase(pid);
aliveQ.erase(valToQPos[pval]);
};
if (pval == X) {
erase_q();
} else if (qval == X) {
erase_p();
} else if (disp >= disq) {
erase_q();
} else {
erase_p();
}
return 0;
}

不断反复调用 choose_p_or_q(),即可啊。

1
2
3
4
5
6
7
8
9
10
11
while (SZ(aliveP) >= 2 || SZ(aliveQ) >= 2) {
int res = choose_p_or_q();
if (res == -1) {
cout << "NO\n";
return;
}
}
cout << "YES\n";
for (int i = 1; i <= ans_idx; ++i) {
cout << Ans[i] << " ";
}

AC代码

AC
https://ac.nowcoder.com/acm/contest/view-submission?submissionId=84410045

心路历程(WA,TLE,MLE……)