码迷,mamicode.com
首页 > 其他好文 > 详细

【Codeforces 1370-D】Odd-Even Subsequence 二分+贪心

时间:2020-07-14 16:37:29      阅读:54      评论:0      收藏:0      [点我收藏+]

标签:个数   min   using   角度   const   span   inline   main   mes   

D. Odd-Even Subsequence

题意

给出一个数组 a ,让你选择一个 a 的子序列,使得 \(min(max(a_1,a_3,a_5...),max(a_2,a_4,a_6...))\) 最小。

即奇数位置的最大值和偶数位置的最大值 的最小值最小。

思路

其实做这道题我还是很懵逼的,因为如果从选数的角度考虑的话,该选那些数字?这个问题不好解决。

后来我想了枚举每个值作为答案的时候,是否合法,这样复杂度比较高,这时就想到了二分。

把原数组排序,设 l = 1,r = n,二分结果分别从奇数,偶数中诞生,为 arr[mid] 是否合法。

怎么检验合法呢?

假如当前二分的是奇数作为答案,首先我们从头开始选,如果这个值小于等于 x (当前二分的答案值),那么把它放到当前选择的奇数当中,这时下一个能选择的距离这个值的距离要大于 1 。就这样选择下去,最后看剩余的数字最大值是不是大于等于 x。

我写完之后突然意识到我没有判断 x 有没有被选择到奇数队列中,因为我们是把 x 作为奇数的最大值,那就要保证 x 要在奇数中,这样一来,竟然不知道该如何检验合法性。便放弃了二分的想法。(其实一直二分下去就对了,不在,说明这个 x 不是最佳答案,我没考虑好)

后想了一个贪心的想法,假如答案在奇数产生,我们只需要保证奇数的所有值尽可能的小。

按照他们的大小把下标进行排序,一次进行选择,如果当前数字的邻居并没有被选择,那么当前数字可以选择。

最后根据判断奇数和偶数产生的答案,输出较小值。Wa6了。

看了一下之前是因为代码写错了wa6了,最后wa9 是因为这样找可能根本找不到满足条件的序列。

题解

直接二分答案,l = 0,r = 1e9 。

这样不用考虑当前二分的 x 在不在当前队列中,不在说明 x 不是最小值 ,继续二分就可以了。

检验的时候检验是否可以找到一个长度为 k 的队列。

看代码理解

#include<bits/stdc++.h>
#define pb push_back
const int N=1e6+10;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
using namespace std;

int arr[N],n,k;
int check(int x,int m)
{
    int num=0;
    for(int i=1; i<=n; i++)
    {
        if(arr[i]<=x||num%2==m)
            num++;
    }
    return num>=k;
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n; i++)
        scanf("%d",&arr[i]);
    int l=0,r=1e9,ans;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(check(mid,0)||check(mid,1))
        {
            ans=mid;
            r=mid-1;
        }
        else
            l=mid+1;
    }
    printf("%d\n",ans);
    return 0;
}

【Codeforces 1370-D】Odd-Even Subsequence 二分+贪心

标签:个数   min   using   角度   const   span   inline   main   mes   

原文地址:https://www.cnblogs.com/valk3/p/13299660.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!