2022.04.04省选模拟赛总结
1.时间安排
7:20~7:50 看题面
T1:图论题,n=2000有70分的高分,感觉很可做。
T2:字符串dp,可能要AC自动机,已经很久没写了。
T3:好像见过原题?
7:50~8:20
确定没读错题后,直接写线段树优化建图的拓扑排序,简单调试一下,需要spj的题大样例居然和标准答案一模一样,就懒得写spj了,直接写前面的题。
8:20~10:00
T1被第二个样例坑大惨了……
一开始想了个 n * m 的搜索,但是样例调不对,发现理解错题意了,浪费半个小时。
想着先写个2^m*m的暴力起码先拿点分,写完又是调了好久,终于把题面样例过了。
但是,下发文件的样例输入不合法……
接着去测下发文件的样例,发现是0。
画出图后,发现答案确实应该是14,就一直在找代码的问题。
一直调到10点都没结果,放弃了。
10:00~11:00
上来又把题意读错了,又浪费20分钟写了错的代码。
仔细分析后把30分dp写出来了。
已经忘了AC自动机怎么写了,就放弃了。
11:00~11:40
继续刚T1,这时候冷静下来看了看样例。
"一共8个点,存在8->9的边,图还不连通?"
当场感觉白白浪费了2个小时,不过及时止损至少还有30分……
又把前面n*m的代码翻了出来,加了map套set判重,虽然大样例答案对了,但是根本跑不动……
匆匆检查低级错误提交。
result:
T1:30 T2:30 T3:100
2.反思
T1:
时间全浪费在错误的下发样例了……
但是点双边双的题目很久没做了,就算有时间也不一定能写出来。
T2:
AC自动机也已经忘完了啊(之前总结里的毒奶成功了……),复习了一下后70分很快就写出来了。
正解的广义矩乘也不难,主要问题还是在AC自动机不熟练上。
T3:
略
3.简要题解
T1:
一句话题意:给出一张n点m边的无向连通图,求所有的只被一个简单环包含的边的编号异或和。
\(n,m\leq 1e6\)
求出所有的点双连通分量。
考虑一个点双连通分量里面的边都被至少一个环包含,当且仅当边数大于等于点数(显然)。但如果边数大于点数,所有的边都会被至少两个环包含。
所以只需要统计有哪些点双的边数等于点数,这些点双里面的边就是要求的边。
在学姐的提醒下,我才发现的代码里有一个致命的细节没注意到,被三角形的菊花hack掉(TLE)。
统计答案时,我的做法是暴力枚举点双内部的点,然后枚举所有与它相连的边,看到达的点是否在同一个点双内。
但是如果是三角形菊花数据,就会因为割点存在于每个点双内部,导致的大量冗余枚举而TLE掉。
正确做法:tarjan求点双,最后加入vector的一定是割点,不枚举这个割点就好了。
这种做法学姐证明了一定是小于等于O((n+m)logm)的,而且根本跑不满。
三角形菊花生成代码如下:
int n=66667,m=99999;
printf("%d %d\n",n,m);
for(int i=2;i<=n;i+=2){
printf("%d %d\n",i,i+1);
printf("1 %d\n",i);
printf("1 %d\n",i+1);
}
T2:
一句话题意:给出m个字符串,每个字符串有一个价值,生成一个长度为n的字符串,价值为m的字符串在n中出现的次数 * 字符串的价值之和,最大化价值。
\(n\leq 1e12,\sum_{i=1}^{m}|s_i|\leq 200\)
70分直接上AC自动机,转移到对应的fail指针即可。
100分的话需要广义矩阵乘法,支持如下运算:
可以先预处理出来转移矩阵,然后就可以对答案矩阵快速幂了。
T3:
4.总结
1.复习
不能再拖了,tarjan,AC自动机这些都要抓紧复习了。
最近列个计划表吧,有空就找几道题复习复习。
2.stl的空间
订题的时候第一遍提交MLE了,检查一遍发现是std::vector爆空间了。
64位系统下常用stl的初始空间(即使是空的):
(单位:字节)
vector: 24
set: 48
map:48
(c++11)unordered_map:56
stl不管储存元素是什么类型的,初始空间都是这么大,所以不能豪爽地直接开1e6甚至1e7个的stl,小心空间。

浙公网安备 33010602011771号