CF/AT 构造,交互,博弈题总结
以后 CF/AT 上的构造,交互,博弈题就放在这里了,其实不光是 CF/AT,别的 OJ 的题也有。题目总结 更倾向于一些阳间传统一点的题。
板刷 CF 计划(。因为蒟蒻太蒻,只能做 *2000
到 *2700
之间的题。目前在这里随机选题做,会把一些好的题而且还是我不会做的那种放到这里来进行总结。
从 CF1402C 开始,到 ? 结束,当前进度:\(?/?(?\%)\)。
SF 的 题单。
独立思考,少看题解!
设 \((opt,x,y)\) 为一次操作 ,首先考虑只有 \(3\) 操作的情况。因为要求的是 \(\displaystyle \prod_{i=1}^n a_i\),那么不难发现乘在哪里都是一样的,所以把所有的值从大到小排序就可以了。
然后我们不难发现一个性质:所有操作必然是先 \(1\),再 \(2\),再 \(3\) 的。
这启示我们把 \(1\) 操作和 \(2\) 操作也转换成 \(3\) 操作(即乘上一个数)。
先考虑 \(2\) 操作。对于同一个下标 \(x\),对他进行的操作必然是要从大到小操作的。那么不妨先从大到小排序。每次操作 \((2,x,y)\),那么就算出这次操作前下标为 \(x\) 的值 \(sum\),那么这次就相当于乘了一个数 \(\displaystyle \frac {sum+y}{sum}\),这样就转换成操作 \(2\) 了。
那么操作 \(1\) 呢?首先,对于每个数,我们只需要找到最大的操作 \(1\),设为 \((1,x,y)\),然后就可以把这个操作转换成 \((2,x,y-a_x)\) 就可以了。
然后把所有乘起来的东西从大到小排序。找到前 \(m\) 个就可以了。
但是,这样子就可能做不到 \(1 \to 2\to 3\) 的顺序了,怎么办呢?实际上,因为乘法满足交换律,对于前 \(m\) 个操作,我们再对于 \(opt\) 从小到大排序就可以满足了。
code。
不得不说我构造题真的啥都不会/kk。
不难注意到如果没有环,那么全部设置为 \(1\) 就可以了。
那么如果有环呢?答案至少为 \(2\)。同时我们可以大胆猜测答案就是 \(2\)。
然后怎么构造呢?不难发现,把每个点当成高度,那么一个环必然由上升的连线和下降的连线组成,其中一个设置成 \(1\),另一个设置成 \(2\) 就可以了。
但是好难想啊qwq,大概是我太菜了吧>_<。
代码太太太简单了,就不放了。
vp 的时候被这题打爆了,绿题都不会做了。(虽然 CF 上评分是 *2200
,我觉得应该蓝的)。
考虑一种很野蛮的构造方法:首先如果图不连通输出 NO
,否则对图进行染色,\(1\) 表示选 \(2\) 表示不选。遍历到点 \(u\) 的时候,如果点 \(u\) 没有被染色过,那么把 \(u\) 染色成 \(1\),并且把所有与其相邻的点染成 \(2\)。然后再遍历与其相邻的点。
看起来非常不正确是不是?然而这是合法的。为什么呢?首先,显然这张图不会有两个 \(1\) 相邻的情况。并且,题目要求在所有连接两个不被染色的点的边都被删除的情况下,这个图满足任意两个点互相可达。此外,每次染色一个新的点的时候,必然可以与之前的一个已经染色的点联通,用归纳法就可以证明整张图是联通的。
此题虽然是 div2 F 题,但是实际难度并没有那么高。我 vp 的时候一直在想所谓 “高明的贪心”,于是就没有想出来。这也启示我们要勇于暴力瞎构造,说不定就对了呢?
code。
又是不会做构造题的一天呢/kk。
下文中令 X
为 \(1\),.
为 \(0\)。
考虑把全部一行的数都变成 \(1\),首先考虑的是每隔一行把它变成 \(1\),然而这样可能会形成环:
00000
01010
00000
会变成
11111
01010
11111
是不可行的。那么考虑每隔两行全部变成 \(1\),比如:
00000
01000
00010
00000
10001
00100
00000
会变成
11111
01000
00010
11111
10001
00100
11111
这样子就不会有环了,而且每个点一定连接在一行中,然而有可能不联通,那么我们就需要让全是 \(1\) 的行与行之间互相联通。可以直接把两行全 \(1\) 的直接拿出来考虑(即考虑 \(n=4\) 的情况)。
一个很 naive 的想法是把第 \(2,3\) 行的第一列都变成 \(1\),这在大多数情况是可行的,然而有个反例:
11111
01000
00000
11111
会变成
11111
11000
10000
11111
又形成环了。注意到,形成环的情况只有 \((2,2),(3,2)\) 所表示的地方是 \(1\)。同时,如果这个成立,那么 \((2,1),(3,1),(2,3),(3,3)\) 都不会有 \(1\)(根据条件),那么让 \((2,2),(3,2)\) 都变成 \(1\) 就可以了。
然后稍微特判一下就好了,写代码的时候由于一些傻逼错误调了很长时间。code。
下文中,一条 \(u \to v\),权值为 \(w\) 的边用 \((u,v,w)\) 表示。
- 考虑一个弱化版的问题:\(l=1,r=2^k\)。
可以考虑归纳的构造,当 \(k=0\) 的时候,\(n=2\) 且连一条 \((1,2,1)\) 的边。
当 \(k>0\) 时,如果已经构造出 \(k+1\) 个点,并且 \(1 \to i(i \ge 2)\) 中的所有路径的权值都在 \([1,2^{i-2}]\) 之间且不重复,那么新增一个点 \(n=k+2\),对于 \(2 \le i \le k+1\),连接一条 \((i,n,2^{i-2})\) 的边。同时还有一条 \((1,n,1)\) 的边,那么从点 \(i(i \ge 2)\) 之间到 \(n\) 的所有路径的权值都在 \([1+2^{i-2},2^{i-1}]\) 之间并且不重复,从点 \(1\) 之间到 \(n\) 的长度为 \(1\),所有的路径并起来范围就在 \([1,2^k]\) 之间了,满足条件。
- 那么再把这个问题加强一点:\(\displaystyle l=1,r=(\sum_{i=0}^k r_i \times 2^i)+1\),\(r_{0...k}\) 即 \(r-1\) 的二进制拆分,\(r_k=1\)。
首先安装上面的方法构造出 \(k+2\) 个点,满足 \(1 \to i\) 的所有路径中都在 \([1,2^{i-2}]\) 之间并且不重复。令 \(n=k+3,w=1\),\(w\) 表示当前 \(1\to n\) 的路径在 \([1,w]\) 之间且不重复,并且连一条 \((1,n,1)\) 的边,对于第 \(i\) 个点,如果连了 \((i,n,w)\) 的边,那么 \(w\) 就可以增加 \(2^{i-2}\)。根据二进制拆分,那么连这条边的当且仅当 \(r_i=1\),这样子就可以构造出来了。
- 回到原问题,我们可以先构造出 \(l'=1,r'=r-l+1\) 的情况,然后最后连一条 \((n,n+1,l-1)\) 的边并且把 \(n\) 加 \(1\) 就可以了。
code。
注意到,当 \(n=2^k\) 的时候,可以通过少于 \(k \times 2^k\) 的操作让 \([1,2^k]\) 变成相同的数,具体的构造方法如下:考虑归纳的进行构造,如果 \(k-1\) 满足,那么把 \([1,2^{k-1}]\) 与 \([2^{k-1}+1,2^k]\) 之间都变成相同的数,然后两两配对就可以,不难发现操作次数是比较少的。
然后我就不会了。运用 ST 表的思想,ST 表是通过找到两个长度为 \(2^k\) 的区间,他们的交集就是询问的区间。同样,在本题中也可以这么干,对于这两个区间构造就可以了。而我做题的时候陷入了思维的死胡同,认为一段区间最多被操作一次,就最终没有想出来,还是思维量太弱了啊。
code。
比赛的时候一直在想点分治之类的东西,就一直没有做出来。
不妨设 \(E_{p_1} < E_{p_2} < \ldots < E_{p_n}\),那么显然有 \(dis_{p_i,p_{i+1}} \le E_{p_{i+1}}-E_{p_i}\),答案就是要最小化 \(E_{p_n}\) 的值。
又有 \(\displaystyle dis_{p_l,p_r} \le \sum_{i=l}^{r-1} dis_{p_{i},p_{i+1}} \le E_{p_r}-E_{p_l}\),那么只要上面的成立,那么这个条件就会成立。那么不妨令 \(dis_{p_i,p_{i+1}} = E_{p_{i+1}}-E_{p_i},E_{p_1}=1\),那么 \(\displaystyle E_{p_n}=1+\sum_{i=1}^{n-1} dis_{p_i,p_{i+1}}\)。只要让 \(\displaystyle \sum_{i=1}^{n-1} dis_{p_i,p_{i+1}}\) 最小就可以了。
那么换一种说法:找到一个排列 \(p_{1,2,\ldots,n}\),\(p_1 \to p_2 \to \ldots \to p_n\) 的距离最小。手画一下不难发现,设起点是 \(s\) 终点是 \(t\),那么整个树中每条边都会经过两次,除了 \(s \to t\) 的边,答案就是 \(2 \times (n-1)- dis_{s,t}\)。显然 \(s,t\) 就是直径。
代码蛮好写的,大概就是 dfs 的时候先走不是到 \(t\) 的边再走到 \(t\) 的边。code。
先考虑 \(m=0\) 的情况,注意到题目要求的东西等价于对于任意 \(i,j\)(\(1 \le i < j \le n\)),有 \(a_j-a_i\ge j-i\)。
转换一下得到 \(a_j-j\ge a_i-i\)。
令 \(b_i = a_i-i\),每次操作可以让 \(a_i\) 变成任意一个数,可以能让 \(b_i\) 变成任意一个树,而且最后的 \(b_i\) 要单调不降。
考虑保留那些数,因为要保留的最多,相当于找到 \(b\) 的最长不下降子序列,这有一个二分的优秀的 \(\O(n\log n)\) 算法。
然后加上限制怎么办呢?把这个序列分成很多段就可以了,然后把每段的答案加起来就行。
code。
CF896B Ithea Plays With Chtholly 珂朵莉!
交互题。我们先考虑一个非常 naive 的方法:对于每次新进的一个数,如果能加到当前第一个空位就加,否则就在当前第一个能修改的位置修改。
这样的正确性必然是没有问题的,但是这样需要的数最多是 \(n\times c\),有可能超过 \(m\) 的限制。
然而,为什么不能再两边分别加数呢?考虑设一个 \(x\)。如果给你的数 \(a \le x\),那么就从头进行上述操作。否则就从尾巴进行这样操作。毛估估一下,显然 \(x= \frac c 2\) 的时候最优。下面来证明一下为啥这是正确的。方便起见,不妨令 \(c\) 为偶数。
设从头开始的长度为 \(a\),那么从尾开始的长度就是 \(n-a\),那么所需的最多操作次数是 \(a \times \frac c 2 + (n-a)\times \frac c 2\),发现刚刚好就是 \(n \times \frac c 2\)。
这样也可以证明为啥是 \(x= \frac c 2\) 的时候最优了:对于任意的 \(x\),最多的操作次数是 \(a \times x + (n-a)\times (c-x)\),当 \(a=0 / n\) 的时候取到两个极值,分别是 \(n \times x\) 或者 \(n\times (c-x)\)。显然有可能超过给定的步数。
CF1515F Phoenix and Earthquake
先考虑无解。
一个显然的事实是:如果 \(\displaystyle \sum_{i=1}^n a_i < x\times (n-1)\) 或者这个图不连通,那就是无解。
手玩一下发现除此之外没有无解的情况了。尝试证明一个非常强的结论:每一个生成树,只要满足 \(\displaystyle \sum_{i=1}^n a_i \ge x\times (n-1)\),那就是有解的。
考虑归纳的证明:对于叶子节点 \(u\):
- \(a_u \ge x\),那么连上 \(u \to fa_u\) 的边就可以了。
- \(a_u < x\),那么删去点 \(u\) 后剩下的 \(n-1\) 个节点的树,根据归纳假设,命题得证。
那么构造也很好构造了,按照上述方法构造就行了:先找一个生成树,对于每个节点,先遍历他所有儿子,然后对于这个点 \(u\),如果 \(a_u \ge x\) 那么就把这个点以及其父亲的边选上,否则就放在最后选。非常好写。
code。
然而有没有别的方法呢?
我口胡了一个方法,但是可能时间复杂度有点假,供君一笑,同时也算是这类构造题的一类启发吧。
还是先弄一颗生成树然后考虑归纳的构造:
因为有 \(n\) 个点,而 \(\displaystyle \sum a_i \ge (n-1)\times x\)。先随便找两个相邻的点 \(u,v\),令 \(y = a_u+a_v\),那么 \(\displaystyle y + \sum_{i\ne u,i \ne v} a_i \ge (n-1) \times x\)。根据鸽巢原理,要么存在一个点 \(p\) 满足 \(a_p \ge x\),或者 \(a_u+a_v \ge x\),前者就随便找一个点缩起来,后者就把 \(u,v\) 缩起来。这样就能够证明必然有解了。
然而时间复杂度可能比较大,而且我不太会优化,写起来也比较麻烦,还是前面那种方法好。如果有神仙实现并且过了请叫我一声qwq。
P7595 「EZEC-8」猜树 EZEC R8 的题质量都蛮高的,点赞!可惜我不会做。
暴力怎么做?一个 naive 的想法是枚举每两个点,显然距离 \(=1\) 的两个点之间有祖先关系,连上边之后从 \(1\) 开始 dfs
一遍即可,时间复杂度 \(\mathcal{O}(n^2)\),输出量 \(\frac {n\times (n-1)}{2}\)。
进行一个 naive 的优化,显然,询问 ? 1 1 x
的效果是查询 \(x\) 的深度,那么显然两个点可能连边肯定需要满足他们的深度差为 \(1\),那么按层确定答案再进行上述暴力,输出量是 \(\sum a_i\times a_i+1\),其中 \(cnt_i\) 表示深度为 \(i\) 的点的数量,最劣条件下输出量是 \(\frac{n^2}{4}+n\),但是可以通过链的部分分。注意到,此时,我们还没有使用过 \(2\) 操作。
还是先求出深度,考虑 \(2\) 操作的作用:对于点 \(i\),所有 \(i\) 的子树中深度为 \(1\) 的节点就是他的儿子,这相当于只用这一次就能直接算出 \(i\) 的所有儿子,输出量是 \(\sum_{i=2}^n size_i+n\times 2\),最劣条件下还是 \(n^2\) 级别的,但是可以通过完美二叉树的部分分。
那么一个 naive 的想法就是把这两者结合一下。具体的,考虑根号分治:设一个值 \(T=sqrt{n}\),对于第 \(i\) 层,如果 \(cnt_i \le T\),那么用前一种方法。否则,用后一种方法。感性理解一下就是对的。
啥还要严谨证明?先鸽子。code。
感觉蒟蒻的思维量还是太少了,蒟蒻还需努力!
CF1521C Nastia and a Hidden Permutation
嘴巴出了一个二分第一个值,然后按照第一个值分类讨论求出所有值的方法,写起来比较麻烦(有很多细节),没去实习,有兴趣可以试试。但是有更优的做法。
注意到,如果你确定了 \(p_x=1\),那么对于每个 \(i\),? 1 x i (n-1)
这个询问可以直接得到 \(p_i\) 的值,接下来要做的就是再 \(\frac n 2 +31\) 的次数内求出 \(1\) 所在的位置。
实际上根本不用这么多步。
为了方便起见,先考虑 \(n\) 为偶数的情况。因为有个 \(\frac n 2\),那么考虑使用二操作两两配对。不难发现,对于一次操作 2 i j 1
,设返回的值为 \(x\):
- \(x=1\),那么有 \(p_i=1\)。
- \(x=2\),那么有 \(p_i=2\) 或者 \(p_j \le 2\)。
- \(x \ge 3\),没用。
那么,可能为 \(1\)的数最多是两个。如果只有一个的话显然就是那一个,否则的话设这两个数是 \(x,y\),再用一次询问 2 x y 1
就可以了。
\(n\) 为奇数的时候同理,就是有一个不能配对的要和别的放一起。。
询问次数:\(\left\lceil\dfrac{3\times n}{2}\right\rceil\)。code。
首先考虑“最优策略”是什么。此题有一个重要的结论:后手必胜,并且可以随便下。
证明如下:在先手下完之后,场面上必然存在奇数个字母,那么忽略空格后必然存在两个相邻的字母相同,那么他们之前又必然存在空格可以填上字母。
所以所谓的“最优策略”只是一个幌子,接下来要算的就是方案数。
不难想象,最后可行的方案必然是形如 \(\text{ABABAB}\) 或者\(\text{BABABA}\) 的形式,并且两两之前可能存在 \(0/1\) 个空格。枚举空格的个数 \(i\) (当然需要保证 \(n-i\) 为偶数),那么对于一个局面它可以对答案产生 \((n-i)!\) 的贡献。而对于局面数,确定了所有空格的位置后就只剩下两个可能。这 \(i\) 个空格的排列方式也不难计算,考虑断环成链:
- 第一个位置不是空格,那么相当于是在 \(n-1\) 个位置中选择 \(i\) 个位置放空格并且两两不相邻的方案数。
- 第一个位置是空格,那么第二个和第 \(n\) 个都不是空格,相当于是在 \(n-3\) 个位置中选择 \(i-1\) 个位置放空格并且两两不相邻的方案数。
而这两个问题实际上都是 CF1523E 的弱化版,方案数为 \(\dbinom{n-i}{i}+\dbinom{n-i-1}{i-1}\)。最终答案就是 \(\displaystyle 2 \times \sum_{(n-i)|2}(n-i)!\times(\dbinom{n-i}{i}+\dbinom{n-i-1}{i-1})\),直接算就好了。
前言:这题貌似有一车做法。
这题乍一看貌似毫无头绪,那么先挖掘几个性质吧。
- 显然对于从根开始的一条路径,必然满足每个节点是前一个节点的倍数。
- 显然值最小的点为根。
- 显然,如果一个数是另外一个数的倍数,那么这个数必然是另外一个数的祖先。
- 显然如果存在相同的 \(a_i\),那么他们在一起必然是最优的选择,可以把他们缩成一个点。
下面对于一个不为最小值的点 \(a_d\),令其所有因子并且在数组中存在的数为 \(d_{1 \dots k}\),那么如果 \(k=0\) 则显然无解,否则他的父亲必然是 \(d_k\),而且需要满足对于所有的 \(1 \le i < k\) 有 \(d_{i+1}\) 是 \(d_i\) 的倍数。
构造就这么简单的完成了,然而这种情况下构造出来的答案不一定是对的,还需要判断是否满足条件。
怎么样的条件是不满足的?若存在不满足条件的点对,那么必然可以找到一对点 \((u,v)\) 满足 \((u,v)\) 不满足条件,但是所有,\(u \to lca(u,v),v \to lca(u,v)\) 上的点对都满足条件,即 \((fa_u,fa_v)\) 满足条件。此外,为了方便起见,不妨假设 \(a_{lca(u,v)}=1\),那么有:
\(\gcd(a_{fa_u},a_{fa_v})=1\)
\(\gcd(a_{u},a_{v})\ne 1\)
又有:\(a_{u}\) 为 \(a_{fa_u}\) 的倍数,\(a_{v}\) 为 \(a_{fa_v}\) 的倍数。
那么显然,如果 \(\gcd(\frac {a_{u}} {a_{fa_u}},\frac {a_{v}} {a_{fa_v}}) \ne 1\) 那么就会出现这样子的情况。
那么如果 \(\gcd(\frac {a_{u}} {a_{fa_u}},\frac {a_{v}} {a_{fa_v}}) = 1\) 呢?
令 \(c_u=\frac {a_u} {a_{fa_u}}\),即 \(\gcd(a_{fa_u},a_{fa_v}) = 1,\gcd(a_{fa_u} \times c_u,a_{fa_v} \times c_v) \ne 1\)。
则要么有 \(\gcd(c_u,a_{fa_v}) \ne 1\) ,要么有 \(\gcd(c_v,a_{fa_u})\ne 1\),但是这样则说明点对 \((a_u,a_{fa_v})\) 或是点对 \((a_v,a_{fa_u})\) 不满足条件,与假设成立。
那么可以说明,如果一个数满足条件,那么则说明对于所有的 \((u,v)\) 满足 \(\gcd(c_u,c_v) \ne 1\),有 \(u\) 是 \(v\) 祖先,或 \(v\) 是 \(u\) 祖先。
可以枚举这个 \(\gcd\) 为 \(p (p \in prime)\),则有所有的 \(p|c_u\) 的 \(u\) 都呈祖先关系。注意到树高是 \(\log\) 级别的,从对深的 \(u\) 开始暴力往上跳,看看能否跳到所有的点即可。
代码有点难写。。code。
简单想象一下,貌似是必然有解的。
然后不难发现,如果给出的字符串是 \(\text{LRLRLRLRL}\) 这样的,那么把所有数从大到小排序,然后第一个放左边,第二个放右边……就可以了。正着做有点困难,考虑倒着做,考虑每次从天平中取出一个砝码,同时令放右边的乘以 \(-1\),那么就需要满足每次删掉一个数,满足剩余的数的个数是正数或者负数。
可以发现,如果排序后将所有奇数/偶数位的数乘以 \(-1\),下一个删掉最前面的数和最后面的数,两个的正负形恰好是相反的,而且删掉后还是满足有序和奇偶并列,这意味着只要先把所有的奇数或者偶数位乘 \(-1\) 那么就可以归纳的构造了。
然后根据最后天平的结果选择奇数或者偶数位乘 \(-1\) 然后维护两个指针即可。
code。
首先:众所周知的,竞赛图缩点后是一条链。
然后我们考虑干这么一件事(说实话我也不知道为什么回去想干这么一件事,可能要经过一番尝试才可以发现吧):找到这个竞赛图中的一条链。
考虑一个个加点:对于原来的一条链 \(a_1\to a_2 \to \cdots a_n\),新加入一个点 \(x\),那么肯定是找到一个位置 \(p\) 满足有 \(a_p \to x\) 和 \(x \to a_{p+1}\) 的链。
首先如果有 \(p \to a_1\) 或者 \(a_n \to p\) 的边可以直接加,否则说明一定有 \(a_1 \to p\) 的边和 \(p \to a_n\) 的边,这也一定意味着存在两个相邻的点满足上述条件。
实际上这是可以二分的:假设当前的范围是 \([l,r]\),每次二分到一个点 \(Mid\),那么如果有 \(a_{Mid}\to p\) 的边,那么意味着 \([Mid,r]\) 中存在满足上述条件的边,否则意味着 \([l,Mid]\) 中存在。
找完链之后,考虑缩点,这个就比较平凡了,考虑从后往前缩点:一开始肯定是最后一个点与前面所有点询问是否有边:如果有就说明最后一个点和前一个点在一个联通块里,否则就不管了。如果有接下来怎么做呢?考虑前一个点和再前面的一个点是否在联通块:先拿最后一个点询问,如果没有再拿倒数第二个点询问……这样子,每个点最后询问为 \(0\) 一次,所以总共的次数是 \(2n\) 的,然后就做完了。
code。有个很阴间的输入格式:他每次询问玩会返回一个你答案对不对,不要忘记读这个数。。
考虑一下确定了顺序之后怎么判断是否可行:从两边往中间看,如果两边都是长度相同的人,那么显然必须这两个人本质相同,否则就是这样子的情况:\(\text{abbccd \dots eeffgg}\)(其中相同的字母表示同一个人的两个符号),那么有可以得到若干条相同的信息,然后观察一下之后可以发现,对于长度为 \(2\) 的一个人,名字是 \(ab\),连一条 \(a\) 与 \(b\) 的边,长度为 \(1\) 的人名字是 \(a\),连一条 \(0\) 与 \(a\) 的边,那么的话任何一个形如上面的结构与一条从 \(0\) 开始经过若干条边又回到 \(0\) 的路径,然后的事情就好做了:
- \(L\) 是偶数,那么只有两种情况:一种是两个相同的串翻转过来,还用一种是中间有一个形如 \(aa\) 的情况。前者的话,那么 \(0\) 所在的连通块内必然要找到一个欧拉回路,找到这个回路之后两边轮流放就可以了。此外所有的边必须存在偶数次。对于后者也是差不多的,但是可以允许一个子环存在奇数次。
- L 是奇数,那么中间一定是 \(\text{abbcc}\) 这样的情况,发现他与一个从 \(0\) 开始的欧拉路径一一对应,而且剩余的边必须只存在偶数次。
略微有些细节。code。