题目链接:https://codeforces.ml/contest/1370/problem/D
Ashish has an array a a a of size n n n.
A subsequence of a a a is defined as a sequence that can be obtained from a a a by deleting some elements (possibly none), without changing the order of the remaining elements.Consider a subsequence s s s of a a a. He defines the cost of s s s as the minimum between:
- The maximum among all elements at odd indices of s s s.
- The maximum among all elements at even indices of s s s.
Note that the index of an element is its index in s s s, rather than its index in a a a. The positions are numbered from 1 1 1. So, the cost of s s s is equal to m i n ( m a x ( s 1 , s 3 , s 5 , … ) , m a x ( s 2 , s 4 , s 6 , … ) ) min(max(s1,s3,s5,…),max(s2,s4,s6,…)) min(max(s1,s3,s5,…),max(s2,s4,s6,…)).
For example, the cost of { 7 , 5 , 6 } \left\{7,5,6\right\} {7,5,6} is m i n ( m a x ( 7 , 6 ) , m a x ( 5 ) ) = m i n ( 7 , 5 ) = 5 min(max(7,6),max(5))=min(7,5)=5 min(max(7,6),max(5))=min(7,5)=5.
Help him find the minimum cost of a subsequence of size k k k.
比较明显能看得出思路是二分答案,然后一种思路是将数列排序后取若干相间隔的数,但这样的话会有个问题:数列两端点的数取与不取的情况很难讨论。
因此考虑另一种思路:顺序取数,用一个bool变量记录当前取的是奇数位还是偶数位,对于奇数位/偶数位取数时保证其满足小于等于mid,对于偶数位/奇数位则无限制条件。这种贪心思路为什么成立呢?
假设我们遇到了一个满足条件的数,它的下一个数也满足条件,那这时应该取哪个数呢?这个就是贪心的核心思想,显然,取的数越前越好,因此直接取当前数即可。
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
struct newdata
{
int label;
long long x;
};
newdata a[200005];
int b[200005];
int n,k;
bool cmp(newdata i,newdata j)
{
return i.x < j.x;
}
int main()
{
scanf("%d%d",&n,&k);
for (int i = 1;i <= n;i ++)
{
a[i].label = i;
scanf("%I64d",&a[i].x);
b[i] = a[i].x;
}
sort(a + 1,a + n + 1,cmp);
int l = 1;
int r = n;
while (l < r)
{
int mid = l + r >> 1;
int cnt = 0;
bool now = false;
for (int i = 1;i <= n;i ++)
if (now)
{
cnt ++;
now ^= 1;
}
else
{
if (b[i] <= a[mid].x)
{
cnt ++;
now ^= 1;
}
}
if (cnt >= k)
{
r = mid;
continue;
}
cnt = 0;
now = true;
for (int i = 1;i <= n;i ++)
if (now)
{
cnt ++;
now ^= 1;
}
else
{
if (b[i] <= a[mid].x)
{
cnt ++;
now ^= 1;
}
}
if (cnt >= k)
r = mid;
else l = mid + 1;
}
printf("%d",a[l].x);
return 0;
}

本文解析了Codeforces竞赛中一道关于寻找子序列最小成本的问题,通过二分查找和贪心策略,实现了一种有效的解决方案。
674

被折叠的 条评论
为什么被折叠?



