尺取、二分、三分(函数)
一、尺取
设置两个下标表示区间的左右端点,根据实际情况推进两个端点求得答案。
/**
给定一个序列a,求a中元素和大于等于s的子序列的最小长度
(保证a中元素都为正)
*/
int take() //尺取
{
int l=1,r=1;
int sum=a[1],ans=inf;
while(r<=n) //s是要查找的元素
{
if(sum<s) sum+=a[++r];
else
{
while(sum>=s)
{
ans=min(ans,r-l+1);
sum-=a[l++];
}
}
}
return ans;
}
二、二分
查找x第一次出现的位置
/**
有一个序列a,a中元素满足单调递增(任意下标i和j满足i<j,则ai<aj)。
查找a中元素q在a中第一次出现的位置。
*/
int binary_first(int x) //二分查找x第一次出现的位置
{
int l=1,r=n; //n是数组大小
while(l<r)
{
int bet=(l+r)/2;
if(a[bet]<x) l=bet+1;
else r=bet;
}
return l;
}
查找x最后一次出现的位置
/**
有一个序列a,a中元素满足单调递增(任意下标i和j满足i<j,则ai<aj)。
查找a中元素q在a中最后一次出现的位置。
*/
int binary_last(int x) //二分查找x最后一次出现的位置
{
int l=1,r=n; //n是数组大小
while(l+1<r)
{
int bet=(l+r)/2;
if(a[bet]<=x) l=bet;
else r=bet-1;
}
return a[r]==x?r:l;
}
C++还有两个函数:
lower_bound() 返回a中第一个大于等于x的元素下标
upper_bound() 返回a中第一个大于x的元素的下标
三、三分
/**
计算凸(凹)函数的最大值(最小值)。
*/
void thrp() //三分
{
double l=1,r=n; //n是数组大小
while(r-l>=eps) //eps是精度,题目会有要求
{
m1=l+(r-l)/3;
m2=r-(r-l)/3;
if(f(m2)-f(m1)>=eps)
l=m1;
else
r=m2;
}
return l;
}