Educational Codeforces Round 159 (Rated for Div. 2)
A - Binary Imbalance
如果全是 0
则显然输出 YES
。对至少有一个 1
的情况,如果存在 0
则一定存在一个 0
和 1
挨在一起的位置,一直往这中间加 0
即可满足要求。
于是只要字符串包含 0
就是 YES
,全 1
就是 NO
。
B - Getting Points
一天的收益可以为
C - Insert and Equalize
把
若能通过
显然最小操作次数就是
处理一组数据的时间复杂度为
加快实现:C++17 起引入 std::gcd(_Mn __m, _Nn __n)
,直接用即可(当然 __gcd(_EuclideanRingElement __m, _EuclideanRingElement __n)
也一样)。
这题有用 unordered_map
被 Hack 了的,原理在 这里,所以慎用 unordered 系列。
D - Robot Queries
好像有很简洁的做法,这里给出一种分治做法。
可以先处理出类似前后缀和的东西,即操作一段前缀后能到达的坐标,从终点逆操作一段后缀后能到达的坐标(不难发现,反转区间不会影响经过整个区间后坐标的变化量),此时可以先处理掉询问中没有被翻转的部分,翻转了的区间分治处理。
套路地分治,每次处理跨过分治中心的询问。利用跨过分治中心的性质,将要翻转的区间分成两半处理,容易发现,新的操作序列就是把左边一段翻转了放右边,右边一段翻转了放左边。于是也把询问拆成两个,右边的询问放左边的长度,左边的询问放右边的长度。
此时从分治中心向两边拓展,左右分别维护 正向移动/逆向移动 能到达的坐标集合,遇到拆分后询问时,先从预处理的 后/前 缀中找出找出走到反转区间 右/左 端点时的坐标,简单变换到以分治中心为原点的坐标系下,判断集合中是否存在需要的
代码实现的时间复杂度是
这题好像也有用 unordered_map
被卡了的。
E - Collapsing Strings
容易把问题转化为:求对于每个
稳定的做法就是用字典树维护所有的
空间更小的做法则是用哈希表维护每个
不过这并不能说明哈希是错的,只能说明寄了的哈希不合理。下面给出两类很容易被 Hack 的字符串哈希(多项式哈希)。
- 自然溢出
- 固定方式且模数乘积并没有大得变态
第一种是众所周知的寄,它本质上是对 __uint128_t
的自然溢出,只要稍微增大
string s; s.resize(1<<12);
s[0]='a'; int n=1;
for(int i=0;i<12;++i) {
for(int j=0;j<n;++j) s[j+n]=((s[j]-'a')^1)+'a';
n<<=1;
}
string ss[2];
for(int i=0;i<(1<<11);++i) ss[0]+=s[i];
for(int i=0;i<(1<<11);++i) ss[1]+=s[i+(1<<11)];
cout<<ss[0]<<"\n"<<ss[1]<<endl;
把它们放在合适的位置就可以构造出 Hack。
Example:自然溢出即使双哈希也寄。
第二种包括了常见的双哈希(取两个
Example:双哈希,但是根号甚至不到
而能活过 Open Hack 的常规哈希(就是 Hacker 能在有限的时间内找到并看懂你的哈希函数的实现的哈希),要么是带随机的,要么是
也就是说,如果时间允许,那么三重甚至四重哈希能显著降低被叉的可能性,这本质上是在提升
时间不允许则可以引入随机成分,但注意:模数为质数是一个很好的性质,随机后仍然要保证所有模数为质数,否则它可能莫名其妙寄掉(参考自然溢出)。于是随机一般在 time(nullptr)
,这点存疑,不知道有没有案例),可以用 chrono::steady_clock::now().time_since_epoch().count()
(相对较高精度的时钟)或 random_device{}()
(虽然 Windows 下不是真随机,但也是由系统产生的安全伪随机数),尽量别用 rand()
,因为 CF 的机子是 Windows,RAND_MAX
只有
赛时以为字典树空间不够,写的 Hash 并且过了 System Test,代码其实还用了一个 unordered_map
,但是并没有人卡(其实也不太好卡,主要是 map
实在跑不过去)。
F - Trees and XOR Queries Again
感觉比前两个简单,因为几年前有过 这题(这下真的是 “Again” 了)。浪费时间写 D 了,没看这题。
询问能否用异或表示,可以转化为询问路径上的点的异或线性基。于是做法类似,因为线性基是可以
由于毒瘤的 Hack,现在倍增要想 AC,必须在合并线性基时加上这么一个优化:插入时不枚举 __lg(x)
,它的实现是(对 uint
):
inline _GLIBCXX_CONSTEXPR unsigned
__lg(unsigned __n)
{ return (int)sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); }
显然是个常数极小的
upd:上面的做法是
本文作者:xzm111
本文链接:https://www.cnblogs.com/xzmxzm/p/CF1902.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步