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

在这里插入图片描述
在这里插入图片描述

从序列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;
}

猜你喜欢

转载自blog.csdn.net/qq_43781431/article/details/107939051