加载中...

2024 ICPC 上海站(BCDGI)

第一场区域赛,惨遭打铁。赛时只出了BCI。赛后补了DG,发现两道题都没有那么难,只能说还得加训。。。

\(C,I\)相对简单一些,就不写题解了。

code_C

B

补得最难绷的一题。先写了一个栈维护\(dfs\)路径的写法,\(TLE15\);又写了一个\(set\)维护结点之间访问关系的写法,\(TLE26\)

我的做法就是维护当前正在搜索的路径,对于下一步搜索的方式,有几种可能性:(设当前走到了点\(u\),下一个目标点为\(v\)

  1. \(u\),\(v\)之间有边 -> 直接走\(u,v\)
  2. \(u,v\)之间无边,但\(u\)可以直达一个未访问过的结点(即不在当前路径上的点)->一定非法,必须要加一条新边\((u,v)\)
  3. \(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\)作比较并调整二分边界即可。

作最大匹配的过程:尽可能把容易匹配的点先作匹配,而不是直接按照顺序作一一匹配(易错!)-> 双指针匹配即可。

代码方面要注意两个问题:

  1. 对于二分的\(mid\),每条直线得到的\(x\)要根据值的正负和直线斜率的正负做到正确取整。具体见代码。
  2. 二分边界要取大一些,这个暂时还没懂为什么。

code

posted @ 2025-02-05 01:57  jxs123  阅读(113)  评论(0)    收藏  举报