【题解】牛客OI周赛8-普及组
推荐使用pdf阅读,下载链接:
(请自行将网站copy搜索)
A.兔子的序列
对于 50% 的数据:题目保证了有一个非完全平方数,而 n=1 因此直接输出输入的数即可。
对于 100% 的数据:
做法1:
可以把 1000 以内的完全平方数打一个标记,然后直接按题意模拟就好了
做法2:
对于完全平方数 x 设 那么 t 是一个整数,因此判断一个完全平方数可以进行如下操作 设 若 那么 x 为完全平方数。该做法可能被卡精度,因此推荐做法1。
std:
https://paste.ubuntu.com/p/c8KG6hk965/
std 为做法1
B.兔子的名字
对于 40% 的数据:各类水法
对于 100% 的数据:
问题就是解决如何判断一个串 s 是否为 t 的子序列,事实上有一个
O(|s|+|t|)的做法,枚举 t 的每一个字符,对于 s 用一个变量指针维护当前匹配到的位置,如果 t 枚举的字符与 s 相等,将变量指针往后移即可,最后判断变量指针是否是最末尾就好了。
std:
https://paste.ubuntu.com/p/Nv2rZwPsb4/
C.兔子的区间密码
对于 30% 的数据:观察到 L,R 都很小,因此直接暴力枚举这两个数,保存一个异或最大值即可。
对于另外 10%的数据:
L=R ,所以可以配合 30 分的做法多加入一个特判。或者直接将 L,R 开为 long long 即可。
for 30% or 40% :
https://paste.ubuntu.com/p/JRh8FZQjBC/
对于 70% 的数据:
T 较小,对于这样的问题,有一个 的做法,trie 树。
将 [L,R] 中的所有数的二进制看做一个串,按高位到低位的顺序压入 trie 树。
考虑枚举每一个 [L,R] 中的数在 trie 上查询,如果有和当前位不同的,那么走与他不同的那个节点,否则走相同的。贪心的想法,对于高位为 1 显然更优。(指二进制下的高位)
for 70%:
https://paste.ubuntu.com/p/s55WNSsMk6/
对于 100% 的数据:
因为[L,R]是一个连续区间,因此不妨考虑构造一个最优解。
考虑有两个数 x y
发现 x 与 y 异或后即为最大数。
因此找到 L 与 R 从高位到低位(二进制下)第一个不同的数
显然有一个 ,有一个 。
因为 x 为高位为 1 的最小数,y 为高位为 0 的最大数。
由此我们构造出了最大答案。
对于 L,R 二进制下相同的位数(这里指高位) 显然无法找到两个数 xor 后使这一位为1。
于是答案即为 L 和 R二进制下第一个不同的数的位置开始往后均为 1 的数。
对于这样的问题,简单的位运算可以做到。
效率
std:
https://paste.ubuntu.com/p/byrtbzmcFQ/
D.兔子的逆序对
对于 20% 的数据,n,m 都很小,因此按照题意模拟,求逆序对的时候用 的写法暴力枚举 (i,j) 即可对于 40% 的数据,操作数不会很大,使用 的写法(归并排序or树状数组) 求逆序对。
对于 60% 的数据,操作数变得太大了,常规的模拟自然是不可能的了。
考虑题目要求,只要奇偶性,那么是不是就可以不用求出逆序对的真正个数,而是对于每一个操作进行奇偶性的维护?
不妨这样考虑,对于反转一个区间 [l,r] ,[l,r] 中的数与 [l,r] 外的数的相对位置是不会改变的,因此逆序对个数不会边。
对逆序对个数有影响的就是区间内的数。
设 x 为区间 [l,r] 中的逆序对个数。
由于没有相同的数,容易发现这样的等式关系:
x+ 顺序对个数=总对数
而反转之后,顺序对将变成逆序对,逆序对将变成顺序对。
设原先的总逆序对个数为 ans
那么反转区间 [l,r] 后答案将变成
总对数为
顺序对个数为
减去原先逆序对个数再加上顺序对个数即是新的对数
化简得
考虑奇偶性的变化,-2x 为偶数,对奇偶性无影响,于是对奇偶性有影响的只和总对数有关。
因此 计算出原序列的逆序对个数,判断奇偶性,对于一个操作 O(1) 维护 ans 的奇偶性
for 60%:
https://paste.ubuntu.com/p/Dkz4TN3xcD/
对于 100% 的数据
在 60% 写法的基础上,将求逆序对个数的方法改为归并排序 or 树状数组即可。
效率
std:
https://paste.ubuntu.com/p/MQztHhJhyt/
std为树状数组写法。
## 总结:
本套题目难度近似 NOIP 普及难度,D 题略思维。
祝各位 NOIP 2019 RP++
完结撒花~
萌兔结尾~
Thanks for watching!
题解代码整理: