二分与前缀和学习总结
二分模板
当看到一个题目具有二段性或者有单调性的时候,可以考虑使用二分。有单调性的一定可以二分,但可以二分的不一定单调。
思路
先假设答案在区间[l,r]中,设置一个随机值将区间分成两段,当l和r相等时,就找到了答案。
二分模板`
整数二分
模块一
当调用check函数之后,目标在右区间时
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
当调用check函数之后,目标在左区间时
模块二
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
浮点数二分
模板
double bsearch(double l, double r)
{
const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求
while (r - l > eps) // 两种写法:此时是用精度控制循环次数,直接控制循环100次也是OK的!
{
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;
}
解题步骤
- 确认区间[L,R];
- 根据题意,找出一个判断条件,满足二段性,且所要找的答案是二段性的分界点。
- 定义一个 mid = (l+r)>> 1。
- 写一个check函数,根据check划分区间。
- 根据区间情况,套用模板,当l=mid的时候 mid要变成l+r+1 >> 1。
前缀和
一维前缀和
首先定义一个sum[]数组,sum[i]代表a数组中前i个数的和。
前缀和运算
for(int i = 1; i <= n;i++)
{
sum[i] = sum[i - 1] + a[i]; //sum[i]=a[1]+a[2]+a[3]+...
}
注:这里的i要从1开始 因为如果从0开始的话 sun[i-1]会取到-1,不存在-1。
查询运算
scanf("%d%d", &l, &r);
printf("%d\n", sum[r] - sum[l - 1]);