1943+1944.Codeforces Round 934 (Div. 1,Div. 2) - sol
20240321
终于差不多把 Div1 补完了(F 当然没补),第一次打 Div 1,还是出了一些小状况的。唉。
没有补 Div 1 F 的逆天题,选择放弃。
Dashboard - Codeforces Round 934 (Div. 2) - Codeforces
Dashboard - Codeforces Round 934 (Div. 1) - Codeforces
2A. Destroying Bridges
There are
islands, numbered . Initially, every pair of islands is connected by a bridge. Hence, there are a total of bridges. Everule lives on island
and enjoys visiting the other islands using bridges. Dominater has the power to destroy at most bridges to minimize the number of islands that Everule can reach using (possibly multiple) bridges. Find the minimum number of islands (including island
) that Everule can visit if Dominater destroys bridges optimally.
。
答案只有可能两种:
然而只有当能删的边数
2B. Equal XOR
You are given an array
of length , consisting of each integer from to exactly twice. You are also given an integer
( ). You need to find two arrays
and each of length such that:
is a subset of is a subset of - bitwise XOR of elements of
is equal to the bitwise XOR of elements of ; in other words, It can be proved that at least one pair of
and always exists. If there are multiple solutions, you may output any one of them.
A sequence is a subset of a sequence if can be obtained by deleting several (possibly none or all) elements of and rearranging the elements in any order. For example, , , and are subsets of but and are not subsets of .
。
容易发现两个相同的数异或起来对答案是没有贡献的,
而区间一定是偶数,所以我们考虑先把所有在同一边的数都选完一定不劣,
然后再去同时选两边相同的数就可以了。代码。
A. MEX Game 1
Alice and Bob play yet another game on an array
of size . Alice starts with an empty array . Both players take turns playing, with Alice starting first. On Alice's turn, she picks one element from
, appends that element to , and then deletes it from . On Bob's turn, he picks one element from
, and then deletes it from . The game ends when the array
is empty. Game's score is defined to be the MEX of . Alice wants to maximize the score while Bob wants to minimize it. Find game's final score if both players play optimally.
The (minimum excludant) of an array of integers is defined as the smallest non-negative integer which does not occur in the array. For example:
- The MEX of
is , because does not belong to the array. - The MEX of
is , because and belong to the array, but does not. - The MEX of
is , because , , and belong to the array, but does not.
。
成功把自己绕进去了,做完 B 才绕出来——但是这道题确实很简单啊。
首先,这个东西跟序列的顺序丝毫没有关系,只会与每个数出现的个数相关。
分析一下每次如何选择的,
假设可能的答案
那么考虑当 Alice 知道她希望选哪些数的时候,那么一定是按照个数 从小到大 依次选,这样一定是最优的。
再放到这道题中,因为每次 Bob 也只能拿掉一个,所以当剩余
所以我们每一次选的都是选只剩一个的最优。
想到这里就做完了,因为如果
也就是说答案就是第二个
这道题感觉就是直接模拟一下怎么去选择,不要一直想二分从而把自己绕进去,Alice 和 Bob 的策略都要考虑。
代码。
B. Non-Palindromic Substring
A string
is said to be -good if there exists at least one substring of length which is not a palindrome . Let denote the sum of all values of such that the string is -good. You are given a string
of length . You will have to answer of the following queries:
- Given
and ( ), find the value of .
A substring of a string is a contiguous segment of characters from . For example, " ", " " and " " are all substrings of " " while " " and " " are not.
A palindrome is a string that reads the same backwards as forwards. For example, the strings " ", " " and " " are palindromes while " " and " " are not.
。
CF 出哈希题还是**的。
看了题目,手玩样例,找找规律,容易发现:
- 对于
aaaaa
这种全部相同的字符串答案是 。 - 对于
ababababab
这种交替的字符串,则所有奇数的 都是不好的,都不能算入,而偶数的 都是好的。 - 对于其他情况的 回文串,只会在
时不好,也就是 都是答案。 - 对于其他情况(一定不是回文串),所有的
都是好的。
于是就做完了,而如何判断一个字符串回文就需要用到哈希。
由于是 CF,为了防止 room 里面有人对着你的代码 hack,所以最好写随机模数的双哈希。
而笔者在场上写的确定模数的双哈希,好在并没有被 hack。代码。
C. Tree Compass
You are given a tree with
vertices numbered . Initially, all vertices are colored white. You can perform the following two-step operation:
- Choose a vertex
( ) and a distance ( ). - For all vertices
( ) such that , color black. Construct a sequence of operations to color all the nodes in the tree black using the minimum possible number of operations. It can be proven that it is always possible to do so using at most
operations.
denotes the number of edges on the (unique) simple path between vertices and on the tree.
。
和上一场的 CF 构造一样——数据范围是给 checker 用的!!!
首先对于树上一层一层染色,我们容易想到对于一条直径来做,
于是从简到难,我们先到考虑一条链的情况嘛。
画图自己分析手玩一下,发现:
- 对于奇数,我们一定对于中间的那个点不断染,次数为
。 - 对于偶数,且
,我们时构造不出来 的情况的,同样对中间的一个点进行操作,最后剩下的两个点一定需要两次操作,所以操作次数也是 。 - 对于
,我们同样想去构造 ,发现是可以的,比如 的情况,我们可以对于第二个点和第三个点分别做一次 的染色,这样的答案是 。
那推广到树上面呢?
发现前两种情况是完全可以的,因为都是对于中间点操作,
而对于第三种情况,我们也希望一种对于中间点操作的策略,
这就很容易想歪,但如果我们对于
于是这也是对于中间的点操作,所以依然是满足条件的。
我们就做完了,每一次只需要找出直径,对直径的中点做相应的操作即可。
时间复杂度是线性的。。。代码。
D1. Counting Is Fun (Easy Version)
An array
of non-negative integers is said to be good if all the elements of can be made equal to using the following operation some (possibly, zero) times:
- Select two distinct indices
and ( ) and subtract from all such that . You are given two positive integers
, and a prime number . Over all
arrays of length such that for all , count the number of good arrays. Since the number might be too large, you are only required to find it modulo
.
。
主打一个经验和找规律。
感觉这个东西很常见啊,但是有什么性质呢?
发现对于一个合法的
为什么呢?(建议自己画图理解一下)
简单来说,就是当
那么有了这个性质,你似乎随便怎么 dp 一下就可以了,
dp 是简单的,你只需要记录一下最后的两个元素是什么,
每次转移的时候讨论一下如何让
再用前缀和处理一下就可以做到
D2. Counting Is Fun (Hard Version)
题意与 D1 相同。
。
如何优化 D1 的 dp?
直接做根本不可能啊!!!
所以我们考虑反过来想,考虑有多少个不合法的位置满足
而精确的个数很明显依然不好考虑,
于是很自然地想到 容斥,于是我们令
那么我们就只需要最后一个元素是什么啦~
我们设
看起来还是
那么转移其实就是枚举一下当前这一位是否合法,
如果我们钦定当前第
而另一种情况就是上一位不合法,那么我们就需要通过
也就是
而现在考虑如何实现这两个东西,发现其实是可以预处理的!
第一种情况直接前缀和就行,而第二种情况可以按照
实现可以具体看代码,于是这样除去
回到刚才设计 dp 时的问题——
发现
因为奇数最后的容斥系数是相同的,偶数的容斥系数是相同的,而转移中奇偶也不影响,
所以我们完全可以在
具体实现可以看代码。代码。
E1. MEX Game 2 (Easy Version)
Alice and Bob play yet another game on an array
of size . Alice starts with an empty array . Both players take turns playing, with Alice starting first. On Alice's turn, she picks one element from
, appends that element to , and then deletes it from . On Bob's turn, he picks at most
elements from , and then deletes it from . The game ends when the array
is empty. Alice's score is defined to be the MEX of . Alice wants to maximize her score while Bob wants to minimize it. Find Alice's final score if both players play optimally. The array will be given in compressed format. Instead of giving the elements present in the array, we will be giving their frequencies. Formally, you will be given
, the maximum element in the array, and then integers , where represents the number of times occurs in the array .
The (minimum excludant) of an array of integers is defined as the smallest non-negative integer which does not occur in the array. For example:
- The MEX of
is , because does not belong to the array. - The MEX of
is , because and belong to the array, but does not. - The MEX of
is , because , , and belong to the array, but does not.
。
好题啊。
首先发现这道题和 A 的区别(除去数据范围)就是每次可以删掉
按照 A 中的思路想,对于 Alice 而言,判断
如果能选完,那么这就是成立的——不难发现答案是具有二分性的,所以可以二分答案(E1 直接暴力也能过)。
那么现在关键在于我们如何去 chk 一个答案是否合法?
此时顺序已经不重要了,所以我们一定可以按照
再想想——思考 Alice 的最优策略——每次选最小的,
那么为了保证我们排序后的序列保序,所以 Bob 的每一次的删除一定是保证
可是后面怎么才能最优呢?
既然 Alice 的顺序已经确定,所以我们只需要让 Bob 最优即可,
而 Bob 最优就是希望在选到某一个位置
为什么没有了?因为在它选
我们把这个
容易发现中断点不同,你前面的策略也是不同的,所以这似乎要枚举。
假设当前枚举到的中断点为
而又要保证 Alice 的选择策略是从左往右(也就是序列保序),当选到
这是什么呢?
容易发现其实就是一个从后往前的推平操作,你直接暴力乱作一下就可以了。
细想一下,由于
每次 chk 的时候我们用
而这时可以用
你加上一个二分可以轻松通过,时间复杂度
代码。
bool chk(int x){//答案是否能为 x
for(int i=0;i<x;i++) b[i]=a[i];
sort(b,b+x);
for(int i=0;i<x;i++) c[i]=b[i];
if(x==1) return true;
if(x==2) return b[1]>K;
if(b[1]<=K) return false;
for(int len=2;len<=x;len++){//枚举中断点
for(int i=0;i<len;i++) b[i]=c[i];
S[len]=0;//预处理后缀和
for(int i=len-1;i>=0;i--) S[i]=S[i+1]+b[i];
for(int i=1,id;i<len-1;i++){
ll s=0,nw=0;
for(int j=i;j<len;j++){//把 j 以后的都推平,也就是都 =b[j]
s=S[j]-1ll*(len-j)*b[j];
if(s<=K){id=j;break;}
}
nw=(K-s)/(len-id);
b[id]-=nw;
for(int j=id+1;j<len;j++) b[j]=b[id];
nw=(K-s)%(len-id);
for(int j=id;j<len&&nw;j++) --nw,--b[j];
}
if(b[len-1]<=K) return false;
}
return true;
}
E2. MEX Game 2 (Hard Version)
题意与 E1 相同。
。
感觉和 E1 的思路其实差别并不大,那么现在我们来想想如何优化 E1 中的 chk 过程呢?
容易发现枚举中断点基本上是跑不掉的,那么如何快速完成判断一个中断点和一个序列是否合法呢?
感觉需要一些模拟:
在 E1 中我们也发现了,其实也就是一个不断推平的过程,
而推平过程中可能会出现很多个不同的数,但是我们发现当不同数的个数减到
具体来说,对于一个长度为
也就是形如
发现这样的序列之后的操作也就有了一个固定的模式,我们对其进行一轮变换(Alice 删一个最小的,Bob 再拿走
它会得到
所以不断这样递归到
而反过来,我们可以从
这时一个简单 dp 可以完成的:
for(int i=1;i<=n+1;i++) f[i]=f[i-1]+K+(f[i-1]+K)/i;
而进而考虑,只要对于每一个中断点,我们找到第一个位置,使得它操作完之后,后面就变成一个平序列的地方,
这个位置后面的所有位置就是非常好处理的了。
发现这时非常好处理的,用双指针或者简单二分一下就可以完成,
因为对于一个位置的判断是好判断的,假设当前二分到的位置是
也就相当于判断
感觉比较抽象可以结合代码理解:
for(int i=2;i<=x;i++){//枚举中断点,s 是前缀和
int l=0,r=i;
while(l<r){
int mid=(l+r)/2;
if(s[i]-s[mid]-1ll*b[mid+1]*(i-mid)<=1ll*K*mid) r=mid;
else l=mid+1;
}
if(s[i]-s[l]<=1ll*l*K+f[i-l-1]) return false;//判断后面平的序列是否合法
}
这里是用二分实现的,但容易发现可以直接用双指针维护,可以少掉一个 不过也无所谓,反正能过)
于是这样我们就做完了,把每一次的 chk 优化到了
Conclusion
- 类似于博弈论的题目一定去模拟情景,考虑双方的最优策略分别是什么即可,不要想复杂了。(A)
- 两人都是最优策略时考虑保证一人最优策略的顺序,再对另一个人的策略贪心。(E1)
- 优化代码时考虑哪些情况之后都规约到一种情况了,于是这部分的枚举时间可以大大减少。(E2)
- 构造题分析清楚再下手,有些非常高妙的构造可以考虑跑暴力。(C)
- dp 优化可以考虑 反过来做容斥!!!(D2)
本文作者:H_W_Y
本文链接:https://www.cnblogs.com/H-W-Y/p/18088227/cf1943
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步