今天考试的第一题还是比较温和,除了它有
O
(
1
0
8
)
O(10^8)
O(108)的时间复杂度让人有些心生畏惧,不太敢写之外,不过好在常数比较小,再加上
1
0
8
10^8
108跑不满,所以就这样过了(最初的转移还有一个
l
o
g
log
log,不过预处理一下就没有了,正解居然就是
1
0
8
10^8
108,所以这道题考的是怎么预处理??)。
事实验证了对拍还是很有用的,检查出来了有一个后来改的地方两数相乘忘了乘1LL再模。
发现回过头去改代码很容易改错,总是会忘记一些限制。
所以,检查的时候:重新读题,记住题目的条件与限制,想一下有那些坑点,代码从头开始阅读,要对它的过程有比较清晰的思路,这时候如果发现不对再去改。改的时候不要心慌。
第二题,MLE,爆零。
正解是在单调栈中二分。
我记得在最开始拿到这个题的时候我是想到过维护单调栈然后二分的,但很快这种思路就被我否定了,原因是好像当时我又分析出了一个线段覆盖的思路,然后莫名开始怀疑单调栈二分的正确性,也担心如果写单调栈二分,那些加加减减,大于小于等于的地方会不会出现一大堆bug,然后根本就调不出来,于是就放弃了这种方法。又因为自认为线段树我是不会写丑的,于是就在MLE的路上一去不返了。(并不知道当时为什么会这么想的)
其实我是算过内存的,差不多241MB,然而算错了,因为并没有意识到开空的vector也是要占内存的
~~。
所以,当遇到拿不准占用的内存,应该:
printf("%d\n",(int)sizeof G);
还有就是,递归地调用函数,也会占用一定的内存。所以,任何时候都不要把空间开在MLE的线上,还是留出较大的空余比较保险。
其实正解思路挺简单的,但当时就那么与它擦肩而过了。
第三题没有什么好的思路,所以也并没有纠结就直接写暴力了,暴力得分与预期一致。
get到一个算法,滚动莫队,适用于方便加入信息,难以删除信息的情况。
还是像原来一样左端点分块,右端点排序。不同的就是左端点的处理,每次就比较暴力地清除(用栈记录修改的东西,出栈时复原),回到该块的右端点,向左扩展即可。很巧妙。