CodeForces - 1370D Odd-Even Subsequence 二分

CodeForces - 1370D Odd-Even Subsequence 二分

題意:從數組中選出一個長度爲kk的子序列,組成一個新的數組aa,要求該數組aamin(max{a1,a3,a5},max{a2,a4,a6})min(max\{a_1,a_3,a_5\},max\{a_2,a_4,a_6\})最小

思路:假設這個答案爲xx,則xx只能取原數組中的某個數,答案最多爲nn種,且這nn個答案具有大小關係,可以按照從小到大排序,且值越大,其限制條件越少,越容易出現。現在要求最小值,因爲滿足單調性,可以採取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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章