CodeForces - 1370D Odd-Even Subsequence 二分
題意:從數組中選出一個長度爲的子序列,組成一個新的數組,要求該數組的最小
思路:假設這個答案爲,則只能取原數組中的某個數,答案最多爲種,且這個答案具有大小關係,可以按照從小到大排序,且值越大,其限制條件越少,越容易出現。現在要求最小值,因爲滿足單調性,可以採取check()二分
CHECK原理:
- 控制第一個最大值最小:設置一個初始值爲0的索引,奇偶索引對應的其實就是得到數組中的位置的奇偶。當索引爲奇數時,就判斷當前數是否小於等於mid,如果否,就一直往下找;如果是,就將索引加1,表示將該數填入數組,此時該索引爲偶數,索引加1,表示該數也填入數組。
相鄰的這個數如果也小於等於mid是不是就浪費了?不算浪費。因爲如果兩個小於等於mid的數相鄰,則取前者更優,可以爲後面提供更多“機會” - 控制第二個最大值最小:同理,只需將奇偶調換即可。
代碼:
const int maxn=2e6+7;
const int INF=1e9;
const ll INFF=1e18;
int n,k,a[maxn];
bool check(int x)
{
int cnt=0;
rep(i,1,n)
{
if (cnt%2)
{
if (a[i]<=x)cnt++;
}
else cnt++;
}
if (cnt>=k)return true;
cnt=0;
rep(i,1,n)
{
if (cnt%2==0)
{
if (a[i]<=x)cnt++;
}
else cnt++;
}
if (cnt>=k)return true;
return false;
}
int main()
{
scanf("%d%d",&n,&k);
rep(i,1,n)scanf("%d",&a[i]);
int l=1,r=INF;
while(l<r)
{
int mid=(l+r)>>1;
if (check(mid))r=mid;
else l=mid+1;
}
W(l);
return 0;
}