考场成绩: $95pt+0+48pt+0=143pt$
现成绩: $100pt+100pt+100pt+65pt=360pt$
P7913 [CSP-S 2021] 廊桥分配
实力贪心,当初真考的时候在我们学校,我当时坐在 B003
时有一份代码,我就替那个人交了,结果那人爆零。然后洛谷就一直留着这道题,后来清题的时候就把这道题给做了。所以留有印象。
分开计算,首先将使用 $1\sim n$ 的国内廊桥能最多停多少和 $1\sim n$ 的国外廊桥能停放多少。然后计算答案则是 $ans=\max(res_{in}[i]+res_{out}[n-i]),0\leq i\leq n$ 。这一步是能够想到的。
对于计算过程,使用两个优先队列,一个 $lQueue$ 来记录一个二元组 $(x,y)$ 表示当前停靠飞机的离开时间和停靠的廊桥编号。另一个 $wQueue$ 来记录当前空闲的廊桥编号,至于为什么是优先队列,因为整个过程秉承“先到先得”的原则,且让廊桥编号尽可能大。最后统计前缀和即可。
好吧,事实上,今天上午并没有做出了这道题,只是翻出了之前的代码,然后贺了上去,虽然之后在摆烂的时候把代码完全搞懂了。但总归不是自己做出来的。AC Code
1 |
|
这道题还有一个思路,是 $\text{LuckyLeaves}$ 的考场思路,用线段树维护廊桥数量的最大停靠数,然后用线段树二分,统计答案时差分即可。
两种思路差不多,线段树二分就相当于是手写了一个优先队列。总的思路还是模拟题意。
P7914 [CSP-S 2021] 括号序列
神仙分讨区间 $\text{Dp}$ ,当初参考的是一个不太复杂的做法:
记状态:$Dp[l][r][6]$ ,表示区间 $[l,r]$ 的 $6$ 种情况。
(说实话,能够把题读懂已经够呛了)这 $6$ 种情况表示了六种超级括号序列的表示。
- $Dp[l][r][0]$ 表示形如 $\ast\ast\dots\ast\ast$ 的括号序列,即全部都是 $\ast$ 的括号序列;
- $Dp[l][r][1]$ 表示形如 $(\cdots)$ 的括号序列,即正好被包裹的情况;
- $Dp[l][r][2]$ 表示形如 $(\cdots)\ast\ast(\cdots)\ast\ast$ 的括号序列,即左边为完整括号,右边为 $\ast$ 的情况;
- $Dp[l][r][3]$ 表示形如 $(\cdots)\ast\ast(\cdots)\ast\ast(\cdots)$ 的括号序列,即左右为括号,但不为同一组括号;
- $Dp[l][r][4]$ 表示形如 $\ast\ast\ast(\cdots)\ast\ast(\cdots)$ 的括号序列,即 $Dp[l][r][2]$ 的左右翻转;
- $Dp[l][r][5]$ 表示形如 $\ast\ast(\cdots)\ast(\cdots)\ast\ast$ 的括号序列,即左右皆为 $\ast$ ,但中间有完整括号。
然后就是转移,令函数 $cmp(l,r)$ 进行判断,$S[l],S[r]$ 是否能够配对成括号,如果能,返回 $1$ ,否则返回 $0$。
- $Dp[l][r][0]$ 直接暴力转移,枚举 $Dp[l][r-1][0]$ 是否存在,按位与即可。
- $Dp[l][r][1]=(Dp[l+1][r-1][0]+Dp[l+1][r-1][2]+Dp[l+1][r-1][3]+Dp[l+1][r-1][4])\times cmp(l,r)$
- $\displaystyle Dp[l][r][2]=\sum_{i=l}^{r}Dp[l][i][3]\times Dp[i+1][r][0]$
- $\displaystyle Dp[l][r][3]=\sum_{i=l}^{r-1}(Dp[l][i][2]+Dp[l][i][3])\times Dp[i+1][r][1]+Dp[l][r][1]$
- $\displaystyle Dp[l][r][4]=\sum_{i=l}^{r}(Dp[l][i][4]+Dp[l][i][5])\times Dp[i+1][r][1]$
- $\displaystyle Dp[l][r][5]=\sum_{i=l}^{r-1}Dp[l][i][4]\times Dp[i+1][r][0]+Dp[l][r][0]$
其实吧,主要在于能不能把所有的情况全部想到并分类表示,然后转移其实就简单了,$n\leq 500$ 乱搞都可以,实际时间复杂度 $\mathcal O(6n^3)$ ,跑不满。
虽然要取模,但是还是要开 long long
。
AC Code
1 |
|
P7915 [CSP-S 2021] 回文
考场暴力,居然只是 T 和 M ,比较顺利。
暴力思路
直接 $dfs$ 或者 $bfs$ ,对于一些优化,我后来思考了一下。因为我们要查找的是字典序最小的,所以肯定是优先 $L$ 才会使用 $R$ 。而对于 $bfs$ 而言,大部分的答案都是一并算出来的,所以在比较答案是必须要全部比较,十分消耗时间。而在使用 $dfs$ 的时候,我们可以在前几次搜索时就搜出了一个备选答案,然后可以在中间段的时候就比较当前搜出的答案和原有答案,减少之后的搜索,可能会有一定优化。
后来发现两个方法的得分是一样的。
还有,我在此以磐岩起誓,再不用 string。考场上用了 string
,然后就快快乐乐地 $CE$ 了。起飞, $\text{Dev-C++}$ 还没报错。
一定要用字符数组,方便又快捷。
48pt by dfs
1 |
|
48pt by bfs
1 |
|
正解
还是得明知,我们所求的方案必是字典序最小的。而且每当我们取一个数,就会有另一个数被定下。且有 $b_1=\{a_1,a_{2n}\}$ ,那么对于这两个数的数目的另一个数,记作 $a_x$ ,则必有 $b_{2n}=a_x$ ,这样想的话其实应该会很容易,读者可以自行模拟。
那么,这道题的正解,就是四指针法。
用作两个指针 $l_1,r_1$ 表示 $b$ 数组的头指针指在的是 $a$ 数组的左端和右端。也就表示区间 $[l_1,r_1]$ 还没有被取到过。而另外两个指针 $l_2,r_2$ 则是 $b$ 数组同理的尾指针,表示区间 $[l_2,r_2]$ 之内的数正好是已经被取到过的数的末尾,可以认为是类似于双向 bfs 那样运作的。那么,整个过程满足 $l_1\leq l_2\leq r_2\leq r_1$,当 $l_1=l_2,r_1=r_2$ 时,表示所有数都被取完,则统计答案。
那如何字典序最小呢,因为一次会记录两个位置,所以有 $LL<LR<RL<RR$ 。对应的情况可以自行思考。当然,前提是转移的两个位置记为 $nxt_1,nxt_2$ 必定满足 $a_{nxt_1}=a_{nxt_2},nxt_1\neq nxt_2$ ,才能够转移,否则不存在答案。我们可以用一个数组 $back[i]$ 表示位置 $i$ 的数 $a_i$ 值的另一个位置在 $back[i]$ 那么,当 $back[nxt_1]=nxt_2$ 或者 $back[nxt_2]=nxt_1$ 时,即可转移。当然,上述两个条件必然是同时满足的,易证。
这道题的复杂度应该是 $\mathcal{O}(kn)$ ,其中,$k$ 是不超过 $10$ 的常数。
AC Code
1 |
|
P7916 [CSP-S 2021] 交通规划
第一次考的时候甚至连题都不想读,然后第二次考的时候做了一下,发现还是可以稍稍做一点部分分的。
纳米暴力,小子
当时想到的,结果还写挂了,不如写网络流。
因为一共有 $nm$ 个点需要我们来染色,那么,一共就有 $2^{nm}$ 种染色方案,暴力跑一遍后求出最小权值即可,时间复杂度 $\mathcal O(nm2^{nm})$ ,目测能跑过 $10pts$ ,结果写挂了,爆蛋。
不贴代码,没意义。
纳米网络流,小子
可以想到,我们需要使两端颜色不同的边权值和最小,也就意味着要使颜色相同的边权值最大,可以想到最小割,考虑建图:
- 连接超级源点和初始颜色为黑色的点,容量为 $inf$ ;
- 连接超级汇点和初始颜色为白色的点,容量为 $inf$ ;
- 连接应该连接的所有边,边权为应该有的边权。
然后跑最大流即可。
但是,点数 $NM+K$ ,边数更是无法计算。
更何况,每一次询问还要单独建图,所以还需要重置询问。
不过,还是有 $65pts$ ,似乎实测 $\operatorname{CCF}$ 只有 $60pts$ 。
TLE Code
1 |
|
纳米正解,小子
已经想到了要在网格图上求最小割,那么就考虑优化网络流。
先考虑网络流的本质:把颜色不同的点隔开。
就需要一个新的知识——对偶图。(这个东西比较抽象,之后再写篇笔记,先搁着)对偶图是网络在网格图上的一个变形图,使得可以使用 $\text{Dijkstra}$ 在 $\mathcal O(n\log m)$ 的时间复杂度内求出最小割。
构造关键点(可以证明关键点一定是附加点),然后用 $Dist[i][j]$ 储存两两关键点之间的最短路径,可以证明最有构造方案中的路径一定不交叉。
有这个性质,还有 $k\leq 50$ ,考虑区间 $\operatorname{Dp}$ 来求解(今年居然把考点考得这么重,两道贪心,两道区间 $\text{Dp}$)。