题意是现在有n个0,给你m段序列,然后给你q次操作,每次操作给一个x,把第x个0变成1,问你最少几次操作能出现一段序列里的1的数量大于0的数量,如果不存在,输出-1
对于操作数是一个递增序列。如果第k次操作后正好可行,那么就不用管k+1及以后了。
所以可以使用二分来解决。
一开始在check函数犯了一个错误,当check k时,成功的条件是当前段里的1的数目*2>段长度,而不应该是(当前段里的1的数目>=k&&k*2>段长度)
代码
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
int n,m,q;
int b[100005];
int a[100005],e[100005];
struct seg
{
int l,r;
}c[100005];
inline bool check(int k)
{
memset(e,0,sizeof(e));
for(int i=1;i<=k;i++)
e[a[i]]=1;
for(int i=1;i<=n;i++)
b[i]=b[i-1]+e[i];
for(int i=1;i<=m;i++)
{
int l=c[i].l,r=c[i].r;
if((b[r]-b[l-1])*2>r-l+1)
//if(b[r]-b[l-1]>=k&&r-l+1<2*k)错误示例
return 1;
}
return 0;
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>c[i].l>>c[i].r;
cin>>q;
for(int i=1;i<=q;i++)
cin>>a[i];
int l=1,r=q;
while(l<r)//log(q)
{
int mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid+1;
}
if(check(l))
cout<<l<<endl;
else cout<<-1<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
标签:Tracking,1843E,段长度,int,Segments,mid,100005,序列,check From: https://www.cnblogs.com/qbning/p/17546115.html