12.4日记
CDQ分治
- HDU1541:给定一些(a,b),定义(a,b)的等级为满足(a2<=a&&b2<=b)的(a2,b2)的个数。输出等级为0-n-1的星星个数。
二维偏序裸题。第一位排好序,第二维树状数组即可。
注意:树状数组不可以处理下标为0的情况,因此需要先+1。或者就直接离散化。离散化的时候,注意int len=unique(a+1,a+n+1)-a-1;
线段树
- HDU4578:区间加减+区间乘+区间修改+区间询问一次二次三次方和。
我tm哭了,debug了一天。既然是取模,所以lazy[id][3]标记在没有值的时候要设置为-1,不是用0判断。
思路:修改最优先,乘其次,加减最后。每次pushdown先判断修改,如果没有修改再进行乘和加减。每次修改值的时候,一次性把123次全都修改。
单调数据结构
- POJ2559:给N个宽度为1的并列的矩形,求选出一个矩形,面积最大。
思路:可以贪心,以第i个矩形为最大模板,能选取的最大面积是左边第一个比他小的位置和右边第一个比他小的位置的距离*h[i],先单调栈求出两边第一个比他小的数,最后再扫一遍,都是\(O(n)\)的。
但对于这种区间最小值*区间长度的最大值的题目,可以直接单调栈处理。
- POJ3494:给一个01矩阵,求最大子矩阵的面积。
思路:太妙了,扫每一个横行,实际上相当于做了n遍最大矩形并面积。
- POJ2796:求区间最小值*区间和的最大值。
思路:和POJ2559一样,只不过这里改成了区间和,求前缀和套单调栈即可。本质上是求出让每个值为最小值的最大区间。
总结
今天调那个线段树调了1w年……服了,以后就长了个教训,不是所有时候都可以用0判断是否存在的,尤其是对于取模的情况。另外学会了单调栈的一些基本应用,主要是找左右第一个最值,进而能够找到使当前值为最小值的最大区间(和CF1073G中qz爷的做法对上了,回头再补一下这个题,毕竟当时自己写的实在是太丑了)。
明日计划
明天比较忙,线段树往前赶一赶,CDQ把二维偏序和三维偏序的裸题写了。