Codeforces 1370D Odd-Even Subsequence(二分)

题意:给出一个长度为n的序列a【】,求选取一个长度为k的子序列b【】,使得val=min(max(b【i】(i%2==1)),b【i】(i%2==0)))的值最小,输出最小的val。n<2e5

题解:显然val必然是a【i】,val是取了一个min,不满足单调性无法二分,但是可以发现,令va=max(b【i=odd】),vb=max(b【i=even】),无论va和vb的大小,最小的即是val,可以尝试对va和vb进行二分,va和vb满足单调性,最小的满足check()的值就是ans。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define fre freopen("C:\\in.txt", "r", stdin)
#define _for(i,a,b) for(int i=a; i< b; i++)
#define _rep(i,a,b) for(int i=a; i<=b; i++)
#define lowbit(a) ((a)&-(a))
#define inf 0x3f3f3f3f
#define endl "\n"
using namespace std;
typedef long long ll;
template <class T>
void read(T &x)
{
    char c; bool op=0;
    while(c=getchar(), c<'0'||c>'9') if(c=='-') op=1;
    x=c-'0';
    while(c=getchar(), c>='0'&&c<='9') x=x*10+c-'0';
    if(op) x=-x;
}

const int maxn=2e5+5;
int T, n, k, a[maxn], idx[maxn];
bool cmp(int x, int y){
    return a[x]<a[y];
}

int check(int x)
{
    int cnt=0;
    _rep(i, 1, n)
        if(cnt&1){
            if(a[i]<=x) cnt++;
        }else cnt++;
    if(cnt>=k) return true;
    cnt=0;
    _rep(i, 1, n)
        if(!(cnt&1)){
            if(a[i]<=x) cnt++;
        }else cnt++;
    if(cnt>=k) return true;
    return false;
}

int main()
{
    //read(T);
    T=1;
    while(T--)
    {
        read(n), read(k);
        _rep(i, 1, n) read(a[i]);
        _rep(i, 1, n) idx[i]=i;
        sort(idx+1, idx+1+n, cmp);
        //_rep(i, 1, n) cout<<idx[i]<<" \n"[i==n];
        int l=1, r=n;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(a[idx[mid]])) r=mid-1;
            else l=mid+1;
        }
        printf("%d\n", a[idx[l]]);
    }
    return 0;
}

 

posted @ 2020-08-06 21:44  N_Yokel  阅读(141)  评论(0编辑  收藏  举报