今天除了补题学会一些新知识外(写了一些博客,这里就不再复习一遍啦),还主要学习了倍增和贪心这部分内容。
倍增
在进行递推时,如果状态空间很大,线性递推无法满足时间空间复杂度要求,那么可以通过成倍增长的方式,即只递推状态空间中2整数幂次位置,其他的位置都可用这些位置来表示。
如果数据很大就是O(n) 和 O(logn)的区别了,可以大大降低时间复杂度。
RMQ(区间最值查询)是一个预处理O(n*logn)区间极值O(1)查询任意区间极值的算法
- 主要思想就是区间dp出每个点起2的k次方的长度内的极值。运用大区间的极值由小区间得到,同时大区间的答案可以由小区间随意组合得到。
- 方法:我们可以找2个小一点的区间可以覆盖需要查询的区间,比如查找5长度的区间,我们已经预处理1为起点长度为4的答案,和2为起点长度为44的答案,我们查询区间1到5的极值就可以比较1-4区间和2-5区间的答案来得到1-5的答案。
- 令
F[i][j]
表示区间[[i,i+2^j-1]
里的数的最大值,边界值为F[i][0]=A[i];最大值F[i][j]=max(F[i][j-1],F[i+2^j][j-1])
.
代码实现:
void ST_prework()//预处理
{
for(int i=1;i<=n;i++)
f[i][0]=a[i];
int t=log(n)/log(2)+1;
for(int j=1;j<t;j++)
for(int i=1;i<=n-(1<<j)+1;i++)
f[i][j]=max(f[i][j],f[i+(1<<(j-1))][j-1]);
}
int ST_prework(int l,int r)//求解只要覆盖区间即可,即使重叠也没有关系
{
int k=log(r-l+1)/log(2);
return max(f[l][k],f[r-(1<<k)+1][k]);
}
贪心
以前,贪心是在我认知里最见到的算法(没有之一),而现在,我表示不想说话啦,像蓝皮上的第一道例题奶牛用防晒霜的题算是最简单的啦,我还要按着贪心的答案一步步去想这样贪心是否正确,所以在这一块,要多见题,熟悉每一类题目的贪心思想怎样贪心以及证明手段(自己好好想想清楚)。
这一块我不太想占用特长时间的,以后遇到贪心的题目再及时总结。
晚上做题,A题是一道水题,B题主要卡个超时,另外,有个暴力的优化,就是不直接执行交换。D题主要用了一个贪心的思想再加一点思维,E题都见过一次啦,但还是没做出来。说明自己根本掌握的不熟,一知半解,这点要尤其注意。做过的题要坚决搞懂。
今天继续把题补一下,然后开启第二章数据结构。