第一场区域赛,惨遭打铁。赛时只出了BCG。赛后补了DG,发现两道题都没有那么难,只能说还得加训。。。
\(C,I\)相对简单一些,就不写题解了。
code_C
B
补得最难绷的一题。先写了一个栈维护\(dfs\)路径的写法,\(TLE15\);又写了一个\(set\)维护结点之间访问关系的写法,\(TLE26\)。
我的做法就是维护当前正在搜索的路径,对于下一步搜索的方式,有几种可能性:(设当前走到了点\(u\),下一个目标点为\(v\))
- \(u\),\(v\)之间有边 -> 直接走\(u,v\)
- \(u,v\)之间无边,但\(u\)可以直达一个未访问过的结点(即不在当前路径上的点)->一定非法,必须要加一条新边\((u,v)\)
- \(u\)之后的结点均已被搜索过 -> 回溯并重复1,2过程。若发现最后回溯到的所有点均无法继续走,则说明这个联通块内的点均已被搜索过。则由题可知直接对目标点所在的另一个联通块\(dfs\)即可,不需要加新边。
我的所有写法都离不开一个致命问题 —— 即需要线性(或者说暴力)维护当前搜索的路径(要想优化维护可能需要一些\(ds\),但不知道咋写),导致可能有些数据会一直让我卡在暴力回溯的部分而\(TLE\)。
最后还是屈服于了递归,写了一个递归来简化维护回溯路径的写法,直接就过了。
ACcode
TLE on 26 code
D
逆天构造题,借用其他博客上的方法补出来了。
可以发现,只要能变换到结尾两个数字都是\(0\)的情况,就一定可以将所有数字都变为\(0\):只需要倒序把剩下的\(1\)都变为\(0\)即可。
所以问题转化为找到一种操作方式,使得结尾两个数字都为\(0\)。
\(n==3\)的时候特判一下,剩下的情况均为\(n>=4\):
只考虑最后的\(4\)个数字,除了最后两个均为\(0\)的情况一定可行,还剩下\(12\)种情况,其中\(5\)种情况可行,\(7\)种情况不可行。具体见代码。
可行的情况一定为\(Yes\),但不可行的情况不一定为\(No\)。因为在这\(4\)个字符前面的字符也可以对这\(4\)个字符产生影响。具体如何影响,需要看从左到右可以过来多少个\(1\)。而对于不可行的\(7\)种情况,是否可以变为可行,也取决于前面可以过来\(1\)的数量。具体可以自己模拟一下。
而如何计算结尾\(4\)个数字之前的串能过来多少个\(1\),这个类似于括号匹配:把\(1\)当成左括号,\(0\)当成右括号。每一个\(0\)可以抵消掉其左侧的一个\(1\)。从\(str[0到n-5]\)遍历一下,就可以得出最多可以有多少个连续的\(1\)结尾,即上述“前面可以过来\(1\)的数量”。
code
G
中位数二分 + 贪心
显然可以二分答案,设正在二分的答案为\(mid\),则可以根据\(mid\)来得到每一条直线能匹配的最大\(or\)最小的\(x\)。
具体地,对于\(a>0\)的直线,任意\(x >= (mid - b) / a\)均满足\(y>=mid\);而对于\(a < 0\)的直线,任意\(x <= (mid - b) / a\)均满足\(y>=mid\);\(a==0\)时,与\(x\)无关,只有\(b >= mid\)时满足\(y >= mid\)。将所有\(a > 0\)的直线对应的\(x\)放入\(pos\)数组中,将所有\(a < 0\)的直线对应的\(x\)放入\(neg\)数组中;
故将直线按照斜率分成\(3\)组:\(>0,<0和=0\)。则剩下的问题就是将\(c\)数组表示的竖线与求得的\(x\)一一匹配,使得\(y>=mid\)的交点数量尽可能多。
显然有一个贪心的想法:\(a<0\)的直线尽可能匹配较小的\(x\),\(a>0\)的直线尽可能匹配较大的\(x\)(证明略)。因此将\(c\)数组排序后,将\(pos\)数组与\(c\)的后缀作最大匹配,\(neg\)数组与\(c\)的前缀作最大匹配,再加上\(a==0\)的情况,即为最大的\(y>=mid\)的交点数量。与\((n + 1) / 2\)作比较并调整二分边界即可。
作最大匹配的过程:尽可能把容易匹配的点先作匹配,而不是直接按照顺序作一一匹配(易错!)-> 双指针匹配即可。
代码方面要注意两个问题:
- 对于二分的\(mid\),每条直线得到的\(x\)要根据值的正负和直线斜率的正负做到正确取整。具体见代码。
- 二分边界要取大一些,这个暂时还没懂为什么。
code