1.寻找符合条件的最大值(即左端答案合法)
while(r>l)
{
int mid=l+(r-l+1)/2;//避免超出范围
if(true)
{
l=mid;
}
else
{
r=mid-1;
}
}
2.寻找符合条件的最小值(即右端答案合法)
while(r>l)
{
int mid=l+(r-l)/2;//避免超出范围
if(true)
{
r=mid;
}
else
{
l=mid+1;
}
}
3.浮点数的二分
1.
while(r-l>eps)
{
}
2.
for(int i=1;i<=100;i++)
{
}
第一种写法容易因为浮点数精度陷入死循环,第二种循环100次的的精度大概在
10
−30
10
−30
10的负三十次方
这里的二分检查过程是从后往前的,套用第一种模板
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int a[100001];
int q[100001];
int vis[100001];
int ok;
int n,k;
int check(int x)
{
memset(vis,0,sizeof(vis));
int sum=0;
int v=0;
for(int i=x;i>=1;i--)
{
if(a[i]==0)
{
if(sum>0) sum--;
continue;
}
if(vis[a[i]]==0)
{
vis[a[i]]=1;
v++;
sum+=q[a[i]];
}
else if(sum>0)
{
sum--;
}
}
if(sum>0) return 0;
if(v<k) return 0;
ok=1;
return 1;
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=k;i++)
cin>>q[i];
int l=1,r=n+1;
ok=0;
while(r>l)
{
int mid=(l+r)/2;
if(check(mid))
{
r=mid;
}
else
{
l=mid+1;
}
}
if(ok) cout<<r<<endl;
else cout<<"-1"<<endl;
}