CEOI 2023

Day1 T1 A Light Inconvenience

很厉害的交互题。

我们翻转标号的顺序,让最右边的人编号为 \(1\),最左边的人编号为 \(N\)。那么每一次的加入和删除就相当于是在前面加入删除。

考虑需要满足的最基本的要求:每一次表演结束之后,编号为 \(1\) 的人的火把必须点燃。这首先说明第 \(N\) 个人的火把需要是点燃的,同时,对于任意的正整数 \(p\),我们有需要满足 \([p+1,2p+1]\) 中存在点燃的火把。

记我们点燃的火把是 \(f_1=1,f_2\dots f_k,f_{k+1}=N\),其中 \(f_i<f_{i+1}\)。对于 \(p=f_i\),我们需要在 \([f_i+1,2f_i+1]\) 中至少存在一个点燃的火把,也就是 \(f_{i+1}\le 2f_i+1\)。最优的情况就是 \(f_{i+1}=2f_i+1\),这样有 \(k=\log_2N+O(1)\),大约只有 \(60\) 不到。

考虑如何处理 joinleave

对于 join,在前面加入 \(p\) 个人,相当于 \(f_i\to f_i+p\),但是我们可以令 \(t=p\),然后就可以将 \(f_i\) 平移回原位,但是我们仍然要将 \(f_{k+1}=N\) 保留在 \(N+p\) 处,如果这是 \(f_{k+1}>2f_k+1\),我们就额外加入一个 \(2f_k+1\) 即可。

对于 leave,去掉了前 \(p\) 个人,这样会对 \(f_i\) 的结构造成很大的影响,而每一个 \(f_i\) 可以对应覆盖的区间就变成了 \([f_i-2p,f_i-p]\),难以在保持原样的基础上进行修改,所以考虑构造一个新的序列 \(\{g\}\),其中 \(g_1=1\)

假设我们已经处理好了 \(g_1,g_2\dots g_i\),我们考虑如何加入 \(g_{i+1}\),显然首先要有 \(g_{i+1}\in[g_i+1,2g_i+1]\)

我们找到最小的 \(j\) 使得 \(f_{j+1}-2p>2g_i+1\),也就是我们有 \(f_j-2p\le 2g_i+1\)。同时 \(f_j-p\ge \dfrac{f_{j+1}-1}{2}-p>\dfrac{2g_i+2p}{2}-p=g_i\)。这也就意味着 \(g_{i+1}\) 所在的区间 \([g_i+1,2g_i+1]\)\(f_j\) 控制的区间 \([f_j-2p,f_j-p]\) 是有交的,贪心的,我们取 \(g_{i+1}=\min(f_j-p,2g_i+1)\)。我们尝试证明这样取 \(g\),总共需要的数量是正确的。

如果 \(g_{i+1}=2g_i+1\),则 \(g_{i+1}\) 相较于 \(g_i\) 翻倍了。
如果 \(g_{i+1}=f_j-p\),考虑 \(g_{i+2}\) 的取值。由于 \(g_{i+1}=f_j-p\),所以 \(2g_{i+1}+1=2f_j+1-2p\ge f_{j+1}-2p\),所以对于 \(g_{i+2}\) 来说,它至少是 \(\min(f_{j+1}-p,2g_{i+1}+1)\)。如果选择了后者,\(g_{i+2}\) 相较于 \(g_{i+1}\) 翻倍了;如果选择了前者,\(g_{i+2}=f_{j+1}-p\ge 2g_i+1\),所以 \(g_{i+2}\) 相较于 \(g_i\) 翻倍了。
也就意味着每增加两个 \(g\) 至少翻一倍,所以 \(g\) 的长度就是 \(2\log_2N+O(1)\) 的。

Day1 T2 Bring Down the Sky Grading Server

神秘题。做法来自官方题解。

\(N\)\(c_1,c_2,f_1,f_2\) 的上界。

这是一个类似于博弈的问题,我们想要维护一个类似 bool solve(c1,f1,c2,f2) 的东西,返回 1 是否能赢。

首先可以判掉很多显然的转移,例如 \(c_1\le 0\) 或者 \(c_2\le 0\),双方都不能攻击(\(c_1-Sf_2\le 0\land c_2-Sf_1\le 0\))等等。

你会发现,会有两个值很关键,也就是 \(c_1-Sf_2\)\(c_2-Sf_1\),令 \(\alpha_1:=c_1-Sf_2\)\(\alpha_2:=c_2-Sf_1\),你可以认为 \(\alpha_*\) 就是实际的攻击力。

引理 1:如果对于某一组 \((\alpha_1,f_1,\alpha_2,f_2)\) 是赢态,则 \((\alpha_1+1,f_1,\alpha_2,f_2)\)\((\alpha_1,f_1,\alpha_2,f_2+1)\) 是胜态;如果其是负态,则 \((\alpha_1,f_1+1,\alpha_2,f_2)\)\((\alpha_1,f_1,\alpha_2+1,f_2)\) 是负态。
证明:对于 \(\alpha_1\to \alpha_1+1\),显然 \(1\) 的操作空间更大了;对于 \(f_2\to 1\),可以认为 \(1\) 多了一次破坏防火墙使自己增加 \(S\) 的机会,且这个 \(f_2\) 不会对 \(2\) 的策略有任何的影响。\(\Box\)

引理 2:如果 \(\alpha_1\ge S\)\(\alpha_2\le S\),则 \(1\) 必赢。
证明\(1\) 可以选择攻击 \(2\),使得 \(\alpha_2\) 变成 \(\alpha_2-\alpha_1\le 0\);这时 \(2\) 攻击时没有意义的,只能选择破坏防火墙(如果没有防火墙可以破坏则是必输),则 \(\alpha_2\) 变成 \(\alpha_2+S\),仍有 \(\alpha\le S\)\(\Box\)

引理 3:如果 \(\alpha_2\ge S\)\(1\) 会选择攻击。
证明:考虑反证法。对于某一组 \((\alpha_1,f_1,\alpha_2)\) 我们找到最小的 \(f_2\)\(f_2>0\))使得 \(1\) 只能通过破坏防火墙赢。则此时 \(\alpha_1\) 会增加 \(S\);由于 \(1\) 赢,所以这是 \(2\) 选择什么策略又是输,所以考虑 \(2\) 攻击的情况。这是状态变成了 \((\alpha'_1=\alpha_1+S-\alpha_2,f_1,\alpha_2,f_2-1)\),由于 \(\alpha'_1\le \alpha_1\),根据引理 1 可知,这意味着 \((\alpha_1,f_1,\alpha_2,f_2-1)\) 是胜态,如果这个状态可以通过攻击获胜,则 \((\alpha_1,f_1,\alpha_2,f_2)\) 也可以通过攻击获胜;如果这个状态不能通过攻击获胜,则只能通过破坏获胜,则 \((\alpha_1,f_1,\alpha_2,f_2)\) 不是满足条件的最小的 \(f_2\)。无论如何都与原假设矛盾,故原命题成立。\(\Box\)

同时我们发现,如果 \(f_2>0\)\(\alpha_2\le 0\),则 \(1\) 可以选择破坏,使得自己 \(\ge S\);同时 \(2\) 也只能选择破坏,这样就转变成了引理 2 中的情况。同时去掉 \(\alpha_1\le 0\)\(f_2=0\) 这两种 \(1\) 策略唯一确定的情况,我们发现我们没有考虑到的情况只有一种:\(\alpha_1,\alpha_2\in[0,S)\)\(f_1\in[0,\dfrac{N}{S}]\land f_2\in[1,\dfrac{N}{S}]\)

发现这样的状态只有 \(O(N^2\ln N)\) 种。

如果我们对于这 \(O(N^2\ln N)\) 个状态提前求出答案,则对于这一部分的答案可以快速回答。对于其他的部分,我们认为最劣的情况下询问复杂度是 \(O(\log N)\) 的,具体的分析可以考虑对于某一组 \((\alpha_1,\alpha_2)\):如果选择攻击,在 \(\alpha_2<0\) 的时候可以直接得到答案,否则会递归成 \((\alpha_2-\alpha_1,\alpha_1)\),递归次数类似欧几里得算法,复杂度是 \(O(\log N)\) 的;如果选择破坏,发现只会有一种情况,就是 \(\alpha_1\le 0\),而这种情况可能导出的所有情况都讨论出来,都会在 \(O(1)\) 步之后会直接返回结果。

但是这样并不能够解决问题,所以考虑在 \(\alpha_1,\alpha_2\in[0,S)\) 的时候,我们还能不能分析出一些可以直接讨论而不需要 DP 的状态呢。

考虑如果说 \(1\) 如果选择破坏,则 \(2\) 会去选择攻击,否则 \(1\) 可以再次选择攻击使得 \(2\) 破坏的收益是 \(S-(\alpha_1+S)=-\alpha_1\)

也就意味着,\(1\) 可以通过一次破坏使得 \(\alpha_1\) 增加 \(S-\alpha_2\)

\(\beta_1:=S-\alpha_1\)\(\beta_2:=S-\alpha_2\)。则 \(1\) 一次破坏的收益就是 \(\beta_2\),如果 \(\alpha_1+\beta_2\times f_2\ge S\),也就是 \(\beta_2\times f_2\ge \beta_1\),则 \(1\) 就可以选择进行 \(f_2\) 次破坏直接获得胜利。

同时,我们也可以类似地讨论 \(2\) 的情况,如果 \(1\) 第一步是攻击,则 \(2\) 选择破坏,可以类似分析得到如果 \(\beta_1f_1\ge 2S\) 的时候,\(1\) 的第一步一定会选择破坏。

而策略不确定的决策数也就降到了 \(\sum\limits_{\beta_1,\beta_2,f_1,f_2}[\beta_2f_2<\beta_1][\beta_1f_1<2S]=O(S^2\ln S)\)

但是还不够。

我们考虑如果让 \(1\) 先破坏 \(x\) 次,则 \(\alpha_1\to \alpha_1+\beta_2x\)\(\beta_1\to \beta_1-\beta_2x\)。又因为原来有 \(\alpha_2-\alpha_1+\beta_1f_1\le S\),所以在 \(\alpha_1\) 进行了 \(x\) 次破坏只有,无论 \(2\) 如何操作都有 \(\alpha'_2\le S-\beta_2xf_1\),也就是 \(\beta'_2\ge \beta_2xf_1\),那么 \(1\) 在做 \(f_2-x\) 次破坏,得到的收益就是 \(\beta_2xf_1(f_2-x)\),在 \(x=\frac{f_2}{2}\) 的时候最优,取到 \(\frac{1}{4}\beta_2f_1f_2^2\),由于 \(2\) 可能会在 \(1\) 进行后 \(f_2-x\) 次破坏的时候将 \(x\) 减少到 \(-S\),也就是 \(\frac{1}{4}\beta_2f_1f_2^2\ge 2S\) 的时候 \(1\) 必赢。对于 \(f_1=0\) 的情况,\(1\) 可以通过在 \(x\)\(f_2-x\) 中间增加一次攻击做到 \(\frac{1}{4}\beta_2f_2^2\) 的收益。

对于不是上述情况的,我们考虑维护这样的一个信息,由于 \(f_1,f_2,beta_2\) 确定了 \(f_1,f_2\)\(c_2\)\(dp_{f_1,f_2,\beta_2}\) 为最小的 \(c_1\) 使得 \(1\) 能赢,显然可以通过二分来得到。

考虑分析状态量,\(\dfrac{1}{4}\max(f_1,1)f_2^2\beta_2<2S\),可以证明这样的状态只有 \(O(S\log S)\) 个,对于每一个进行一次二分,会有 \(O(S\log^2S)\) 次求答案。而每一次求答案需要 \(O(\log^2S)\) 的时间复杂度。

而在实际代码实现的过程中,所有上面粗的分析都可以通过直接计算来精确的判断是否必赢/输。而对于不能让 \(2\) 通过破坏获胜之类的情况,可以找到 \(1\) 至少要将 \(\alpha_1\) 增加到多少才能够保证;以及有 \(\alpha_1\le 0\land \alpha_2\le 0\) 的时候可以直接让双方破坏到有一方 \(\alpha_*>0\)

实现细节比较多,感觉理解这个东西还是需要看代码。所以最终复杂度为 \(O(S\log^4S+Q\log S)\)

Day1 T3 Brought Down the Grading Server?

首先考虑 \(S=2\) 的怎么做。我们把每一个处理器核心对应的两个测试点看作是一条边 \((u,v)\),则我们要做的事情本质上就是对所有的边进行定向:\(u\to v\) 表示 \(u\)\(1\) 时刻测试,\(v\)\(2\) 时刻测试;\(v\to u\) 表示 \(v\)\(1\) 时刻测试,\(u\)\(2\) 时刻测试。

也就是对于每一个点,它的出度表示第一个时刻的测评数量,入度表示第二个时刻的测评数量。假设所有的测评的出现次数都是偶数,也就对应着每一个点的出度和入度数量相等,也就意味着原图构成了一组合法的欧拉回路。

如果都出现次数为奇数的数,我们可以添加一个额外点,和所有出现测次数为奇数的数对应的点相连,可以证明这个点的度数也是偶数。这样原图仍然存在欧拉回路,同时也可以保证每个点入度和出度的差距 \(\le 1\)

现在考虑如何处理 \(S>2\) 的情况,假设当前 \(S=2^k\),我们想到递归成 \(S=2^{k-1}\) 的子问题。

我们把前 \(2^{k-1}\) 个时刻分成一组,后 \(2^{k-1}\) 个时刻分成一组。如果我们让每一个数在这两组中的出现次数之差 \(\le 1\),我们在递归到左右两侧,在拼接到一起,最后任何两个时刻的数量只差仍让 \(\le 1\)

考虑使用和 \(S=2\) 类似的方法处理这个问题,我们在如 \(t_i\)\(t_{S+1-i}\) 之间连边,也用类似于额外点来补齐到偶数度数。由于这是仍然有欧拉回路,所以这样分成两组的方式是一定存在的。

时间复杂度满足 \(T(S)=2T(\dfrac{S}{2})+O(nS)\),所以最终时间复杂度为 \(O(nS\log S)\)

Day2 T1 Tricks of the Trade

加入我们购买了区间 \([l,r]\) 内的所有机器人,我们必然是卖出区间内 \(s\)\(k\) 大的。

我们记 \(f_{l,r}\) 为区间 \([l,r]\)\(k\) 大的 \(s\) 的和,减去 \([l,r]\)\(c\) 的和。

对于 \(l_1<l_2<r_2<r_1\),我们可以证明 \(f_{l_1,r_2}+f_{l_2,r_1}\ge f_{l_1,r_1}+f_{l_2,r_2}\),具体的,\(c\) 的那一部分是相同的,\(s\) 的那一部分是比较典的分析。

这也就意味着我们记 \(g_r=\max f_{l,r}\),取到最值的 \(l\) 是有单调性的,也就是决策单调性。

对于单个 \(f\) 的求值可以直接使用主席树,我们可以使用分治的方法做到 \(O(n\log^2n)\) 求出对于每一个 \(r\) 来说最优的 \(l\)。这样我们就解决了第一问。

现在考虑第二问,由于我们只找到了最优的决策点,但是实际上取到最优解的区间可以有 \(O(n^2)\) 的,显然暴力找到每一个区间是不现实的。

但是我们考虑,如果存在两个最优解区间 \([l_1,r_1],[l_2,r_2]\),满足 \(l_1<l_2<r_2<r_1\),则我们有 \(f_{l_1,r_2}+f_{l_2,r_1}\ge f_{l_1,r_1}+f_{l_2,r_2}=2ans\) 的,但是 \(ans\)\(f\) 的最大值,所以有 \(f_{l_1,r_2}=f_{l_2,r_1}=ans\),而 \([l_1,r_1]\) 中的前 \(k\) 大,必然会被 \([l_1,r_2],[l_2,r_2],[l_2,r_1]\) 中的前 \(k\) 大的覆盖,所以我们就不需要考虑 \([l_1,r_1]\) 这个区间的贡献。

具体的,对于每一个 \(r\),我们找打最大的那个最优的 \(l\),则我们只需要对于每一个 \(g_r=ans\) 的右端点,从左往右进行一个扫描线状物即可。可以使用线段树维护有哪些节点已经被作为最优的出现了,每一次相当于删除区间内 \(s\ge lim\) 的数,那么这一部分的复杂度可以做到势能的 \(O(n\log n)\)

时间复杂度 \(O(n\log^2n)\)

Day2 T2 The Ties That Guide Us

考虑到我们可以走 \(d+30\) 步,也就是我们可以有大概 \(15\) 次走错的机会。

首先看一下部分分:只有一个点的度数为 \(2\)。也就是我们的树可以变成一个完全二叉树的形态,也就意味着我们确定了一个根。

那么我们走最短路的方式就比较明了了:先跳到 \(lca\),然后再往下跳。

我们将 \(safe\) 节点到根的路径上的点标记为 \(1\),其余的标记为 \(0\)。那么对于跳到 \(lca\) 的那一步,我们就一直跳父亲,跳到一个标记为 \(1\) 的节点为止。

对于向下跳的部分,由于二叉树上每一个节点都只有两个儿子。我们可以借鉴重链剖分的思想,先尝试跳重儿子,如果不是,就返回跳轻儿子。由于每一个点到根的路径上最多只有 \(\log_2n\) 次跳轻链,所以我们最劣只有 \(log_2n=15\) 次操作。

我们发现,这个部分分给我们提供了一个做法:确定树的一个根。

但是由于树的编号被打乱了,所以我们无法基于编号找到这样的根,所以只能基于树本身的性质。自然而然想到的是重心。

这样就会出现两个问题:

  1. 重心的儿子数有三个。
  2. 重心可能有两个。

对于第一个问题,其实只有重心这一个点可能出现这种情况,所以我们按照重量从大到小访问它的每一个节点,发现仍然是大约 \(15\) 次。

对于第二个问题,如果两个重心都被染成了 \(1\),则可能会出现跳到了根,但是它有两个儿子被染成 \(1\) 的情况(其中一个是另一个重心,一个是真正的路径),所以我们钦定距离 \(safe\) 更近的那个重心为根即可。在最后跳根的时候如果发现到了根都没有遇到 \(1\),就跳到另一个重心上即可。

Day2 T3 How to Avoid Disqualification in 75 Easy Steps

\(R=10,H=1\)

由于两个主席在同一个位置,可以认为是同一个主席。

我们考虑二进制分组,可以询问出 \(a\) 的每一位是否是 \(1\),需要 \(\left\lceil\log_21000\right\rceil=10\),刚好。

\(R=H=20\)

我们考虑可以通过对 \([1,1000]\) 二分来得到 \(\min(a,b)\) 的位置,然后我们可以通过对 \([\min(a,b)+1,1000]\) 二分得到 \(\max(a,b)\) 的位置。

\(R=30,H=2\)

我们考虑沿用第一种做法,但是我们同时询问这一位是 \(1\) 的以及它的补集。如果 \(a\)\(b\) 的某一个二进制位相同,则对于这一位的答案就确定了;否则,这一位 \(a\)\(b\) 将会是一 \(1\)\(0\)

对于不确定的这些位 \(p_1,p_2,p_3\dots p_k\),我们询问 \(p_1,p_i\) 相同的数中是否有主席,如果有,说明 \(a,b\)\(p_1\)\(1\) 的数 \(p_i\) 也为 \(1\)

这样需要两次询问,其中第一次问 \(20\) 个,第二次最多问 \(9\) 个。

\(R=70,H=1\)

我们考虑沿用第三问的做法,但是我们需要提前处理出第二次需要的所有询问,也就是需要 \(20+\binom{10}{2}=65\) 个询问。

考虑二进制不一定是最优的,考虑使用三进制,则也可以用类似的方式进行处理,由于 \(\left\lceil\log_31000\right\rceil=7\) 需要的询问数是 \(3\times 7+\binom{7}{2}=42\)

据说四进制可以做到 \(4\times 5+2\binom{5}{2}=40\) 个。

感觉这样的构造是没有前途的,我们考虑一下我们要做的事情的本质是什么,如果对于某一个位置 \(i\),它被访问的机器人集合为 \(R_i\)。则我们需要通过机器人返回的情况 \(R\) 来唯一确定一组 \(i\le j\),满足 \(R_i\cup R_j=R\)

我们将 \(R_i\) 考虑成一个二进制数的话,我们就是要构造出 \(1000\) 个数使得两两或和互不相同。

感觉没有什么很好的构造方式,所以考虑退火或者搜索。

posted @ 2024-03-26 09:22  Xun_Xiaoyao  阅读(47)  评论(0编辑  收藏  举报
/* 鼠标点击求赞文字特效 */