A
- 首先有一个显然的直觉:直接拿最大的,然后后手就拿不了了,赢!
- 然后发现一个显然的问题:最大的有很多个怎么办?
- 接着毕加思索这个问题:
- 如果最大的数有奇数个,那两个人都只能依次取走,最后先手必胜
- 如果最大的数有偶数个,那么同理,先手必输
- 所以有一个很显然的结论:如果最大的数的个数是偶数,我们绝对不能碰!
否则,我们只需要取最大的数就能赢
- 现在我们讨论最大数的数量是偶数个的情况,有没有什么办法能让后手不得不去取走最大的数呢?
- 有!如果次大数是奇数个,那么同理,后手将不得不去取最大数,我们就可以赢
- 但是,次大数也是偶数怎么办?有没有什么办法能让后手不得不去取走次大的数呢?
- 有!如果次次大数是奇数个,那么同理,后手将不得不去取次大数,我们就可以赢
- 但是,次次大数又是偶数怎么办?......
- 所以,只要所有种类的数种有一个是奇数个,先手一定存在必胜策略,即取最大的奇数个的数,然后跟着后手取;否则,后手一定存在必胜策略,即跟着先手取
B
- 考虑构造(废话
- 如果要保证索引 \(x\) 是最大前缀和,那么索引 \(x+1\) 处必定为 \(-1\),且 \(x+1\) 处的后缀和必定小于等于 \(0\)
- 如果要保证索引 \(y\) 是最大后缀和,那么索引 \(y-1\) 处必定为 \(-1\),且 \(y-1\) 处的前缀和必定小于等于 0
- 注意到前两个条件对 \(y-x\) 之间的位置没有约束,于是我们果断全都设为 \(1\),因为这显然对于构造合法答案是不劣的
- 考虑极端数据:\(x,y\) 贴到一起了,即序列中间的这部分一定可以提供的正数值在最少情况下只有 \(2\)
- 如果要保证 \(x\) 索引是最大前缀和,则需要保证 \(y\) 之前的位置的前缀和最小为 \(-1\)(否则就没法保证 \(x\) 这个位置是最大前缀和了)
- \(y\) 与之对称,反之同理
- 综合以上,我们有构造方案:
- \(x-y\) 之间都设 \(1\)
- \(y-1\) 设 \(-1\),再往前是 \(1,-1\) 交替
- \(x+1\) 设 \(-1\),再往前是\(1,-1\) 交替
C
- 首先注意到一次操作后,序列会永远单调不减,这是个很好的性质
- 有一个很 naive 的想法是,我们尝试刻画一下一次操作之后的序列,大概长这样:
a...ab...bc...cd...d
- 没什么思路,于是继续手模一下,发现一次操作后,序列整体右移一位,高位补 0
- 于是我们直接写 \(ans=a_i\times (n-i+1)(a_i是一次操作后的序列)\) 然后非常快速地 WA 掉了样例
- 观察样例发现了一个问题:如果一次操作后的序列里有单一的数,那这个数再经过一次操作就无了,但是只要出现过两次,就会一直右移直到序列全 0
- 所以我们只需稍加改进:先暴力模拟两次操作,然后令 \(ans+=a_i\times (n-i+1) (a_i是操作两次后的序列)\) 即可
D
- 很好的考察思维严密性的题
- 这种题一开始没什么思路,我们可以通过样例,手模和脑渲得出一些很 naive 的结论,然后尝试用这些结论拼凑出一些不 naive 的东西来
- 注意到:方形最多只能贡献两行,所以如果当前行要染白至少需要两个方形的话,则直接放弃方形
- 注意到:染方形的位置只有两种:第一个格子和第三个格子。为什么?如果染了第二个格子,则第一个格子还至少需要染一次,虽然可能可以继续向下一行贡献,但这样的贡献相当于继续重复这一递归过程,且一定存在重复染色,显然不优于染第一个格子;如果染了第四个格子,则前三个格子至少还需要染两个格子,显然更劣于染第三个格子;再继续往后,显然劣完了
- 所以使用方形的情况其实只有两种:
- \(a_i\leq 2\) 直接方形,向下贡献
- \(a_i\leq 4\) 并且被上一行贡献过,则把黑的地方用方形补完,向下贡献
- 手动模拟一下并统计答案即可
E
- 提供两种做法:随机化乱搞+正解
- 解决三个版本的问题:ez_version(E1) hard_version(E2) bonus_version(加强版)
随机化
- 注意到:如果一次询问的结果为 \(0\),你可以删除这棵子树。
- 考虑随机化,设当前可行的点集为 \(S\),每次询问从 \(S\) 中随机选取一个点,按照题意模拟,直至剩下 \(1\) 个点。
可以证明根据数学直觉,这样做的时间复杂度是 \(O(\log n)\) 的,由于这道题的交互库并不 adptive,所以可以随便过掉所有版本的问题
正解
HARD_VER
- 注意到:如果我们已经确定了鼹鼠一定在从根节点开始的一条链上,那么二分最多 \(13\) 次询问就可以找到鼹鼠
- 于是,问题变为用 \(147\) 次询问如何将其确定在这样一条链上。
- 注意到:如果一棵子树的返回为 1,那么一直访问这个子树的叶子来把鼹鼠赶出这个子树
- 定义节点 \(x\) 到根的距离为 \(dep_x\),到子树 \(x\) 内最深的节点的距离为 \(ped_x\)。
- 注意到,如果已经确定了鼹鼠在子树 \(x\) 里,那么我们可以通过 \(ped_x\) 次操作将其赶出这棵子树,使其在一条满足要求的链上。
- 考虑每次查询一个 \(x\) 使得 \(ped_x=\sqrt{n}\),如果返回 \(0\) 就删除子树 \(x\),否则用 \(\sqrt{n}\) 次将鼹鼠赶到一条满足要求的链上,如果没有这样的子树,即所有 \(ped_x\) 都小于 \(\sqrt{n}\),那么直接用 \(\sqrt{n}\) 次使其到达根节点。
- 不难发现如果删除的话,每次会删除至少 \(\sqrt{n}\) 个节点,所以最多只能删 \(\sqrt{n}\) 次,所以询问次数最多为 \(2\sqrt{n}\),不超过 \(141\)
VERY_HARD_VER
- 我们需要通过不超过 \(87\) 次操作将鼹鼠赶到一条满足要求的链上。
- 每次,我们找一个点 \(x\),使得以 \(x\) 为根的子树为一条链,而且以 \(x\) 的父亲为根的子树不为一条链。
这样的好处在于,如果我们确定鼹鼠在子树 \(x\) 里,我们无需将其赶出这棵子树,可以直接二分。
- 不过,这种做法下,我们的时间复杂度为 \(O(n^2)\),能过,但没啥用
posted @
2024-11-11 21:30
yeyou26
阅读(
37)
评论()
编辑
收藏
举报