QOJ.ac

QOJ

Limite de temps : 2 s Limite de mémoire : 512 MB Points totaux : 100 Communication

#2810. 速通

Statistiques

Marcel 开始进行速通(speedrun),希望能创造新的世界纪录(WR)。遗憾的是,他无法掌握新发现的技巧,因此他必须找到一种方法来获得不公平的优势。

他试图精通的游戏名为《Tree Souls III》,他正尝试在 full-tree% 类别中获得 WR。

顾名思义,游戏发生在一棵树上(即一个有 $N$ 个顶点、编号从 $1$ 到 $N$ 且有 $N-1$ 条边,且无环的图)。

游戏规则如下:角色被放置在树内的一个任意节点上。他可以选择一个整数 $x$,并尝试从他所在的节点走到节点 $x$。如果 $x$ 与他当前所在的节点之间有一条边,他就会移动到 $x$,否则什么也不会发生。如果他至少访问过每个节点一次,他的速通即为有效。

现在,作弊的部分来了:由于他不知道“边传送故障”(edge-teleportation-glitch),他打算为他的世界设置种子,因此在开始速通之前,他会知道树的结构。如果他只是记住了树的结构,那么他作弊的意图就太明显了,他会立即被速通社区封禁,因此他只是在每个节点上放置一些提示(通过篡改代码)。提示是一个长度为 $l$ 的二进制字符串(每个节点上的提示长度 $l$ 相同)。当他位于某个节点时,他可以读取分配给当前节点的提示。

交互

这是一个双重交互问题!

你的代码将被运行两次,一次用于第一次交互(提示设置阶段),另一次用于第二次交互(速通阶段)。

你必须实现以下函数(且不能实现 main 函数):

void assignHints(int subtask, int N, int A[], int B[]);
void speedrun(int subtask, int N, int start);

使用以下可调用函数:

void setHintLen(int l);
void setHint(int i, int j, bool b);
int getLength();
bool getHint(int j);
bool goTo(int x);

提示设置阶段。这是你代码的第一次运行。在此阶段,评测系统的代码将恰好调用一次 assignHints 函数。它将传入子任务索引 subtask 和 $N$ 作为参数,并通过 AB 传入树的边:对于每个 $i = 1, \dots, N-1$,在 $A[i]$ 和 $B[i]$ 之间有一条边。然后,你必须恰好调用一次 setHintLen 函数,并将你决定使用的提示长度作为参数传入。调用 setHintLen 后,你可以多次调用 setHint(i, j, b) 函数。这会将节点 $i$ 的提示的第 $j$ 位设置为 $b$。位索引从 $1$ 到 $l$。提示初始时全部填充为零。在此阶段,你不得调用 getLengthgetHintgoTo 函数。当你完成提示分配后,你的代码应从 assignHints 返回。

速通阶段。这是你代码的第二次运行。在此阶段,评测系统的代码将恰好调用一次 speedrun(subtask, N, start) 函数,告知你速通者开始的节点 start 以及 $N$ 的值。此外,你还会通过参数 subtask 接收子任务的索引。然后,你可以调用 getLength() 函数,它返回你在第一阶段设置的提示长度 $l$;调用 getHint(j) 函数,它告诉你当前所在节点的提示的第 $j$ 位;以及 goTo 函数。如果传给 goTo 的参数是与当前节点有边相连的节点的索引,则该函数返回 true 并且你移动到该节点。否则,它返回 false 并且你不会离开当前节点。在此阶段,你不得调用 setHintsetHintLen 函数。在访问树中所有节点后,你的代码应最终从 speedrun 函数返回。

数据范围

  • $1 \le N \le 1\,000$
  • 令 $Q$ 为 goTo 返回 false 的调用次数。以下概述了为了在每个子任务中获得分数必须遵守的 $l$ 和 $Q$ 的限制。

子任务 1(21 分)

  • $l \le N$
  • $Q \le 2000$
  • 如果所有测试点均正确解决,则该子任务得 21 分,否则得 0 分。

子任务 2(8 分)

  • $l \le 20$
  • $Q \le 2000$
  • 树是一颗星形图;即存在一个节点 $x$ ($1 \le x \le N$),它与所有其他节点相连。
  • 如果所有测试点均正确解决,则该子任务得 8 分,否则得 0 分。

子任务 3(19 分)

  • $l \le 20$
  • $Q \le 2000$
  • 每个节点的度数最多为 2。
  • 如果所有测试点均正确解决,则该子任务得 19 分,否则得 0 分。

子任务 4(12 分)

  • $l \le 316$
  • $Q \le 32000$
  • 如果所有测试点均正确解决,则该子任务得 12 分,否则得 0 分。

子任务 5(40 分)

  • $Q \le 2000$
  • 每个测试点的得分 $s$ 计算如下:如果 $l > 40$,则 $s = 0$。如果 $l \le 20$,则 $s = 40$。否则,$s = 60 - l$。也就是说,如果 $l = 40$,你将获得该测试点一半的分数;如果 $l \le 20$,你将获得该测试点的满分。子任务的得分为该子任务中所有测试点得分 $s$ 的最小值。

样例

在第一次交互(提示设置阶段),选手的函数将被调用如下:

assignHints(
/* subtask = */ 1,
/* N = */ 5,
/* A = */ {-, 1, 2, 3, 3},
/* B = */ {-, 2, 3, 4, 5});

该函数反过来可以选择设置 $l = 2$:

setHintLen(/* l = */ 2);

然后将所有提示位设为 0,除了节点 2 的第 1 位设为 1:

setHint(
/* i = */ 2,
/* j = */ 1,
/* b = */ 1);

然后它退出。选手程序的第一个实例现在将终止,因此该程序存储在内存中的任何数据都将丢失。此时,除了节点 2 的提示为 "10" 外,每个节点的提示均为 "00"。

在第二次交互(速通阶段),选手的函数将被调用:

speedrun(
/* subtask = */ 1,
/* N = */ 5,
/* start = */ 1);

作为回应,该函数开始速通这棵树:

getLength(); // = 2
getHint(1); // = 0
getHint(2); // = 0
goTo(2); // = true
getHint(1); // = 1
getHint(2); // = 0

此时,你最初在节点 1,发现 $l = 2$ 且节点 1 的提示是 "00",然后成功移动到节点 2 并发现节点 2 的提示是 "10"。执行可以继续如下:

goTo(2); // = false (你不能从节点 2 回到它自身)
goTo(5); // = false (从节点 2 到节点 5 没有边)
goTo(3); // = true
goTo(4); // = true
goTo(3); // = true
goTo(5); // = true

此时所有节点都已到达,因此 speedrun 函数可以退出。$Q = 2$,因为有 2 次 goTo 调用返回了 false

Discussions

About Discussions

The discussion section is only for posting: General Discussions (problem-solving strategies, alternative approaches), and Off-topic conversations.

This is NOT for reporting issues! If you want to report bugs or errors, please use the Issues section below.

Open Discussions 0
No discussions in this category.

Issues

About Issues

If you find any issues with the problem (statement, scoring, time/memory limits, test cases, etc.), you may submit an issue here. A problem moderator will review your issue.

Guidelines:

  1. This is not a place to publish discussions, editorials, or requests to debug your code. Issues are only visible to you and problem moderators.
  2. Do not submit duplicated issues.
  3. Issues must be filed in English or Chinese only.
Active Issues 0
No issues in this category.
Closed/Resolved Issues 0
No issues in this category.