CSP-S 2019初赛知识点总结之二分、倍增、贪心

二分

这里

while (l + 1 < r)
{
    int mid = (l + r + 1) >> 1;
    if (check(mid)) l = mid;
    else r = mid;
}
if (check(r)) printf("%d\n", r);
else printf("%d\n", l);
while (l <= r)
{
    int mid = (l + r) >> 1;
    if (check(mid)) l = mid + 1;
    else r = mid - 1;
}
printf("%d\n", r);
while (l < r)
{
    int mid = (l + r) >> 1;
    if (check(mid)) r = mid;
    else l = mid + 1;
}
printf("%d\n", l);
while (l + 1 < r)
{
    int mid = (l + r) >> 1;
    if (check(mid)) r = mid;
    else l = mid;
}
if (check(l)) printf("%d\n", l);
else printf("%d\n", r);
while (l <= r)
{
    int mid = (l + r) >> 1;
    if (check(mid)) ans = mid, l = mid + 1;
    else r = mid - 1;
}
printf("%d\n", ans);

倍增

这是一篇非常优秀的博客:https://blog.csdn.net/JarjingX/article/details/8180560

但是,在这里不讲这种过于形象的方式了,意会即可

来自这里

RMQ(区间最值查询) 是一个预处理O(nlogn)区间极值,O(1)查询任意区间极值的工具

主要思想就是区间dp出每个点起2的k次方的长度内的极值。运用大区间的极值由小区间得到,同时大区间的答案可以由小区间随意组合得到。比如我们已经预处理1为起点长度为4的答案,和2为起点向后4的答案,我们查询区间1到5的极值就可以比较1-4区间和2-5区间的答案来得到1-5的答案;

预处理的代码如下

f数组的意思是以i为起点2的j次方长度的区间的极值是多少

ST算法

void ST_prework()
{
    memset(f, 10, sizeof(f));
    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] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}

模拟一下:我们要得到f[1][1]就可以通过f[1][0]和f[2][0]得到 f[1][2]可以由f[1][1]和f[3][1]得到。由于我们是小区间得到大区间,所以比如求区间大小为8的时候,我们已经处理了所以4大小的区间了

查询极值如下

int ST_query(int x, int y)
{
    int k = log(y - x + 1) / log(2);
    return min(f[x][k], f[y - (1 << k) + 1][k]);
}

在这里插入图片描述

贪心

贪心是一种在每次决策时采取当前意义下最优策略的算法,因此,使用贪心算法要求问题的整体最优性可以由局部最优性导出。

常见的证明贪心算法正确性的手段有:

1.微扰(邻项交换)

2.范围缩放

3.决策包容性

4.反证法

5.数学归纳法

贪婪算法可解决的问题通常大部分都有如下的特性(看着还可以):(来自这里

⑴ 有一个以最优方式来解决的问题。为了构造问题的解决方案,有一个候选的对象的集合。

⑵ 随着算法的进行,将积累起其它两个集合:一个包含已经被考虑过并被选出的候选对象,另一个包含已经被考虑过但被丢弃的候选对象。

⑶ 有一个函数来检查一个候选对象的集合是否提供了问题的解答。该函数不考虑此时的解决方法是否最优。

⑷ 还有一个函数检查是否一个候选对象的集合是可行的,也即是否可能往该集合上添加更多的候选对象以获得一个解。和上一个函数一样,此时不考虑解决方法的最优性。

⑸ 选择函数可以指出哪一个剩余的候选对象最有希望构成问题的解。

⑹ 最后,目标函数给出解的值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值