第一次正式打 Div1 诶…… 现在还是只做出来了 A~D……
开赛前慌得一 bi,感觉肯定要掉分了,最后还是分数真香
Part1. 小结
Codeforces 也打了好久了,看到自己的 Rating 曲线也还是比较曲折的……
从最开始比初始分还低到后来慢慢涨;然后有一次Div2打的比较开心(把F题玩出来了,瞬间跑到rank 24去了~)可以看到就是在紫名下面一点点;下一场就上紫了;后来也是非常爆炸,连续挂了两场(第二次FST了两道 QwQ)……
终于到现在 rating 还是处于 1979 的状态~
毕竟还是第一次正式参加 Div1(注册比赛的时候本来想注册 Div2,结果都不允许我注册,当时心态就崩了),感觉还是不一样,有种打 AGC 的感觉……不过确实,少了 Div2 的 AB 两道水题,后面的题就更有价值了。
Part2. 中文题面
当然是简化了的
A - Ivan the Fool and the Probability Theory
给一个 $n\times m$ 的方格图染色,每个格子只能染成白色或黑色,要求任意格子需要满足“与它相邻的格子中最多只有一个与它颜色相同”,这里的“相邻”指的是四联通(上下左右)。
求染色的方案数模 $10^9+7$。
数据规模:$1\le n,m\le10^5$。
B - The World Is Just a Programming Task (Hard Version)
一来就 Hard Version 了……
给出一个长度为 $n$ 的括号字符串 $S$,你需要交换 $S$ 的两个位置的字符得到字符串 $S’$(交换的两个位置可以相同,相当于不变)。
对一个括号字符串 $T$,定义一个优美值:
满足 $0\le i<n$ ,且“将 $T$ 旋转 $i$ 次后,是一个正则括号序列”的 $i$ 的个数。其中“旋转 $i$ 次”是指把 $T$ 的末尾 $i$ 个字符移动到开头,比如 "abcdef"
旋转 $2$ 次就是 "efabcd"
。
求 $S’$ 的优美值最大是多少,取得最大值时,交换了 $S$ 的哪两个位置的字符得到 $S’$(输出任意解)。
数据规模:$1\le n\le300000$。
C - Queue in the Train
这是一道阅读理解题
火车上有 $n$ 个人依次坐在标号为 $1$ 到 $n$ 的座位上。第 $i$ 个人从 $t_i$ 时刻开始想去接水,每个人接水都需要花费时间 $T$。由于只有一个水龙头,人们可能会排成一个队伍等待接水。
但是显然大家都不想排队,当第 $i$ 个人想去接水时,他会先看第 $1$ 到 $i-1$ 个人有没有去排队接水。如果都没有去(或者已经接完水回来了),他就会去排队接水;否则他会留在座位上等待。
有一个潜规则是:如果在同一时间,有多个人想去接水,而且他们前面都没有人去排队接水,他们中编号最小的那个人会去排队,而其他人会留在座位上等待。
现在给出 $n,T$ 以及 $t_i$,求每个人接完水的时刻分别为多少。(假设人从座位上去排队花费的时间忽略不计,且当一个人接完水,下一个人立即开始接水)
数据规模:$1\le n\le10^5$,$1\le T\le10^9$,$0\le t_i\le10^9$。
两个栗子,帮助理解:
Input Output Explain 3 10
2 1 030 20 10 第③个人在时刻0发现①②都没有排队,就去接水;
第②个人在时刻1发现①没有排队,就排在③的后面;
第①个人在时刻2发现前面没有人,就排在②的后面。5 314
0 310 942 628 0314 628 1256 942 1570 ①⑤在0时刻同时想去接水且发现前面没有人在排队,按照潜规则,①去排队,而⑤等待;
②在310时刻想去接水,但是①还在接水,继续等待;314时刻①回来了,②⑤都想去接水,则②去排队,⑤继续等待;
②在628时刻接完水,同时④想去接水了,此时④⑤都想接水,则④去排队,⑤仍然等待;
④在942时刻接完水,同时③想去接水了,此时③⑤都想去接水,则③去排队;
③在1256时刻接完水,然后⑤看到前面的人都接完水了,去接水,在1570时刻接完。
D - Catowice City
有 $n$ 个人,每个人有一只猫。每个人都熟知自己的猫,但有人还认识其他一些人的猫。
现在要组织一场猫赛(??),要从这 $n$ 个人中选出几个裁判、从这 $n$ 只猫中选出一些参加猫赛。为了保证公平,需要满足没有任何一个裁判认识任何一只参赛的猫。而且显然至少要有一只猫参加比赛、至少有一个裁判。还要要求裁判和参加比赛的猫的总数恰好为 $n$。
给出 $n$ 和 $m$ 条认识关系 i j
,表示第 $i$ 个人认识第 $j$ 个人的猫(并不说明第 $j$ 个人认识第 $i$ 个人的猫),保证每个人都认识自己的猫。
求是否存在一种选择人和猫的方案,满足上述条件。如果存在,输出选择了多少个人和多少个猫,以及选择的是哪些人、哪些猫。
(多组数据)
数据规模:
数据不超过 $10^5$ 组,所有数据的 $n$ 之和以及 $m$ 之和均不超过 $10^6$;单组数据 $1\le n\le m\le10^6$。
Part3. 解析
A - Ivan the Fool and the Probability Theory
这是一道结论题,结论我打表打出来的……
大概就是“斐波那契数列第$n$项和第$m$项之和 乘 2”。
B - The World Is Just a Programming Task (Hard Version)
代码实现得非常丑陋,不要看 qwq
对于一个括号串,其实它的优美值就是它“最多能够被分成多少连续的段使得每一段都是正则括号串”。比如说 "(()())()"
最多能够分成 "(()())"
和 "()"
,它的优美值是 $2$。其实就是最外层括号的数量。
先计算出不交换(也就是交换相同位置)的情况下 $S$ 的优美值。
然后考虑交换,首先应该 交换原本匹配的一对括号,否则会使原来分离的两个(或多个)正则括号串合并成一个正则括号串,根据我们新定义的优美值,这样一定是不比原来优的。
其次,为了改变括号串的优美值,我们 要么交换最外层的一对括号,要么交换第二层的一对括号。
交换最外层的一对括号,会使 交换的括号内的原本的第2层括号变为最外层、原本在该括号之外的最外层括号变为第2层。
比如交换
"(()())()"
的第一个和第六个字符,会使原来(()())
中的()()
变成最外层,而原本不被第一个和第六个字符包含的第7,8个字符变成第2层。交换第二层括号,会使 它包含的第3层括号变成最外层,交换后的左右括号分别与第一层的左右括号配对,其他括号不会受影响。
比如交换
"((())())"
中的第 2,5 个字符,得到"()()(())"
,原本是第3层的第3,4个括号变成了最外层,交换后的第 2 个字符与原来最外层的第 1 个字符构成一对最外层括号、第 5 个字符与原来最外层的第 8 个字符构成一对最外层括号。
这样的话,$O(n)$ 枚举然后计算就好了。
C - Queue in the Train
不难想到先把所有人按 $t_i$ 排个序;
然后参考了 叶ID 的思路,将操作“事件化”,就有以下两种事件:
typ=1 id=i tim=t[i]
:第 $i$ 个人在 tim 时刻想去接水了,开始等待;typ=2 id=i tim
:第 $i$ 个人在 tim 时刻接完了水,回到座位上。
所有事件都按发生时间 tim 排序。如果有一个 typ=1
的事件与 typ=2
的事件同时发生,应该先处理 typ=2
的事件,因为实际上应该是一个人先接完水回来,然后想去接水的人发现自己前面没有正在排队的人,然后就去排队。如果有多个 typ=1
的事件同时发生,根据潜规则,应该按 id 较小的排在前面。
可以用 priority_queue
维护事件,然后用一个 set
维护当前正在排队的人、用一个 priority_queue
维护当前想去接水但正在等待的人。一开始有 $n$ 个 typ=1
事件,即第 $i$ 个人在 $t_i$ 时刻想接水了。
Tab. “正在排队的人” 的
set
的变量名是que
;“正在等待的人”的priority_queue
的变量名是wat
。
除此之外还要处理两个变量:Ntim
,当前时刻;Etim
,当前队列中所有人都接完水的时刻。
接下来就依次处理事件:如果当前事件是
typ=1
,则把这个人放入wat
中;typ=2
,则把这个人移除que
;- 每次处理完一个事件,就查看当前的
wat
的堆顶,如果堆顶表示的这个人前面没有人排队,就把他放入que
中,并且计算他接完水的时间为max(Ntim,Etim)+T
,并且更新Ntim
,Etim
。
还是比较好写的 ~
D - Catowice City
因为一共要选出 $n$ 个人和猫,而每个人认识的自己的猫,所以每个人要么是人去当裁判,要么是他的猫去参加比赛。
所以我们只要决定有哪些人是他的猫去参加比赛即可。
由于认识关系是单向的(即 i 认识 j 的猫但 j 不一定认识 i 的猫),我们可以把认识关系转成一个有向图:如果 i 认识 j 的猫,就连接 i 到 j 的有向边(但是不连接自环)。
这样的话,我们要决定把点分为“人”和“猫”两类,使得不存在从“人”指向“猫”的边。
于是有一种情况是有向图中出现了环,那么环上的所有点都必须选相同的,否则环上一定有从人指向猫的点。如果所有 $n$ 个点都在环上,就一定无解,因为选不出“人”或“猫”来。
如果存在一个(缩点后)入度为零的环,我们就可以把这个环全部选成“猫”,而其他点都选为“人”,显然不会有“人”指向“猫”的边。这一点想通后,除此之外的其他情况无解也就可以理解了。
如果没有环,那就直接选择一个入度为零的点作为“猫”就可以了。
其实总结起来,无论是入度为零的点还是环,都是一个强连通分量,因此先 Tarjan 把强连通块缩点,然后判断每个点的入度就可以了。
(然后其实这就是 2-sat,每个点有“人”和“猫”两种状态;“ i 认识 j 的猫”限制了“如果 i 选人,那 j 就不能选猫”)
Part4. 源代码
A - Ivan the Fool and the Probability Theory
1 | /*Lucky_Glass*/ |
B - The World Is Just a Programming Task (Hard Version)
1 | /*Lucky_Glass*/ |
C - Queue in the Train
1 | /*Lucky_Glass*/ |
D - Catowice City
1 | /*Lucky_Glass*/ |
The End
Thanks for reading!
Email: lucky_glass@foxmail.com,欢迎提问~