考试过程
感觉这套题的T1T2都很可做
所以这次就趁机对做题顺序稍作改变,前1h比较高效地思考,
T1先想到了一个$msqrt{N}$的分块做法,总觉得是个二分,然后就想到了一个$n log^{2}_{n}$的做法
大概算了一下可能会被卡,但又想不出更好的,
T2想了会部分分但是不太确定,T3概率觉得很不好打,就弃了,
于是就开始打T1,打着就发现了很多细节考虑不到,等打完之后发现只剩1h了
没过样例,只好先写T2暴力,然而发现过不了第三个样例,更加绝望,看了半天觉得dp没错,只好先放着回去调T1
最后没有调出来啊。。。本来以为这次可以翻身。
自己代码能力太弱了啊!!如果觉得很难实现的东西,可以先停一下看看有没有更简单的实现方式。
T2暴力写跪了!!有负数情况下取最大值一定要初始化-INF
题解
T1「递归」
本来想写二分,但是码力太弱了,就写了题解第二种
我们考虑这样一种情况,在a,b两个单调序列中选出前k个数
那么我们只需要去看a,b的第k/2个的大小,若$a_{mid}<b_{mid}$那么说明前a的前mid个一定在最终结果里
那么在剩下的区间中继续递归下去解决子问题,k每次减半复杂度log
注意边界:k==1,l1>r1, l2>r2,
特殊处理l1+mid>r1,l2+mid>r2的情况
T2「线段树优化DP」「单调栈」
定义f[i]表示考虑到i,在i处有断点,的最大贡献
然后枚举j [0,i-1]转移时+cal(min)
那么就可以用线段树维护dp最大值,那么cal(min)呢?
可以发现,在一个点扫过去之后,某个点作为最小值所覆盖的区间是不变的,所以就可以接着用线段树维护了,
每次扫完这个点之后,把这个点往前能覆盖到的区间[l-1,r-1]进行区间覆值,
然后再维护一个mx就好
注意每次pushup的时候 t[k].mx=t[lc].mx+t[rc].mx
在对dp值或cal值进行了赋值操作后直接 t[k].mx=t[k].dp+t[k].cal
当然dp值也是pushup