Codeforces(D. Odd-Even Subsequence)二分+奇偶选数

Codeforces(D. Odd-Even Subsequence)二分+奇偶选数_第1张图片
Codeforces(D. Odd-Even Subsequence)二分+奇偶选数_第2张图片

从序列s中选一个子序列a
要求a中的奇数下标的数的最大值为u,偶数下标的数的最大值为v,ans=min(u,v)求最小的ans
二分答案,然后判断答案是否满足
即从s中取一串不连续的数,这些数都小于等于要判断的值
并把这串数分别从当做奇数下标和偶数下标分别取一次
代码:

#include 
#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;
}

你可能感兴趣的:(题解)