从序列s中选一个子序列a
要求a中的奇数下标的数的最大值为u,偶数下标的数的最大值为v,ans=min(u,v)求最小的ans
二分答案,然后判断答案是否满足
即从s中取一串不连续的数,这些数都小于等于要判断的值
并把这串数分别从当做奇数下标和偶数下标分别取一次
代码:
#include <bits/stdc++.h>
#define ll long long
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
template<class T> inline void read(T &x){
x=0; register char c=getchar(); register bool f=0;
while(!isdigit(c))f^=c=='-',c=getchar();
while(isdigit(c))x=x*10+c-'0',c=getchar(); if(f)x=-x;
}
using namespace std;
ll a[200005];
ll n,k,op=-1;
ll query(ll x)
{
int i=1,r=0,w=0;
while(i<=n)
{
if(a[i]<=x)
{
r++;
if(i!=n)
{
w++;i+=2;}
else
{
i++;}
continue;
}
i++;
}
if((r+w)>=k){
return 1;}
i=1;r=0;w=0;
while(i<=n)
{
if(i==n){
w++;break;}
if(a[i+1]<=x)
{
w++;r++;
i+=2;
continue;
}
i++;
}
if((r+w)>=k){
return 1;}
return 0;
}
int main()
{
scanf("%lld %lld",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
op=max(op,a[i]);}
ll left=1,right=op,ans;
while(left<=right)
{
if(left==right){
ans=right;break;}
if((left+1)==right)
{
if(query(left)==1){
ans=left;break;}
else{
ans=right;break;}
}
ll mid=(left+right)/2;
if(query(mid)==1)
{
right=mid;}
else
{
left=mid+1;}
}
printf("%lld\n",ans);
return 0;
}