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