二分: 整数二分和浮点数二分
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。 但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
整数二分
int erfen(int a[],int l,int r,int k)
{
if(l==r)
{
if(a[l]==k) return l;
else return -1;
}
int mid=(l+r)/2;
if(k<=a[mid]) erfen (a,l,mid,k);
else erfen(a,mid+1,r,k);
}
可以找到k在区间(l,r)中所在的位置,若没有,就返回值-1
浮点数二分
例如找一个数的三次方根
#include <iostream>
#include <stdio.h>
using namespace std;
int main() {
double n;
cin>>n;
double l=-100,r=100;
while(r-l>1e-8)
{
double mid=(l+r)/2;
if(mid*mid*mid<=n) l=mid;
else r=mid;
}
printf("%.6lf\n",l);
return 0;
}
当r-l足够小时,我们就假定已经找完,用公式表示为r-l>1e-6,此时有个精度问题如果要求保留六位小数则r-l>1e−8 ,总要比保留的位数多两位。
前缀和
前缀和的使用方便在于:能够降低时间复杂度
输入一个长度为n的整数序列。接下来再输入m个询问,每个询问输入一对l, r。对于每个询问,输出原序列中从第l个数到第r个数的和。
例:输入一个长度为n的整数序列。
接下来再输入m个询问,每个询问输入一对l, r。
对于每个询问,输出原序列中从第l个数到第r个数的和。
#include <iostream>
using namespace std;
const int N = 100010;
int n, m;
int a[N], s[N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
for (int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + a[i]; // 前缀和的初始化
while (m -- )
{
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", s[r] - s[l - 1]); // 区间和的计算
}
return 0;
}
差分:可以看成前缀和的逆运算。
例:AcWing 797. 差分
//差分 时间复杂度 o(m)
#include<iostream>
using namespace std;
const int N=1e5+10;
int a[N],b[N];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i]-a[i-1]; //构建差分数组
}
int l,r,c;
while(m--)
{
scanf("%d%d%d",&l,&r,&c);
b[l]+=c; //表示将序列中[l, r]之间的每个数加上c
b[r+1]-=c;
}
for(int i=1;i<=n;i++)
{
b[i]+=b[i-1]; //求前缀和运算
printf("%d ",b[i]);
}
return 0;
}
位运算