题意
在 长 n 的 序 列 a 中 保 留 k 个 数 , 此 时 令 新 的 子 序 列 为 s 在长n的序列a中保留k个数,此时令新的子序列为s 在长n的序列a中保留k个数,此时令新的子序列为s
统 计 所 有 奇 数 索 引 上 的 最 大 值 和 偶 数 索 引 上 的 最 小 值 , 二 者 取 小 就 是 花 费 统计所有奇数索引上的最大值和偶数索引上的最小值,二者取小就是花费 统计所有奇数索引上的最大值和偶数索引上的最小值,二者取小就是花费
你 要 让 这 个 花 费 最 小 你要让这个花费最小 你要让这个花费最小
分析
二 分 , 分 为 奇 数 索 引 贡 献 答 案 和 偶 数 索 引 贡 献 答 案 二分,分为奇数索引贡献答案和偶数索引贡献答案 二分,分为奇数索引贡献答案和偶数索引贡献答案
Ⅰ . 奇 数 索 引 贡 献 答 案 的 最 小 值 \color{Red}Ⅰ.奇数索引贡献答案的最小值 Ⅰ.奇数索引贡献答案的最小值
此 时 先 二 分 一 个 答 案 m i d , 然 后 去 c h e c k 此时先二分一个答案mid,然后去check 此时先二分一个答案mid,然后去check
因 为 奇 数 索 引 要 选 ( k + 1 ) / 2 个 数 , 而 且 选 的 数 不 能 比 m i d 大 因为奇数索引要选(k+1)/2个数,而且选的数不能比mid大 因为奇数索引要选(k+1)/2个数,而且选的数不能比mid大
否 则 就 认 定 失 败 ( 因 为 是 一 直 取 m a x ) 否则就认定失败(因为是一直取max) 否则就认定失败(因为是一直取max)
那 么 我 们 从 索 引 1 开 始 往 后 看 , 一 旦 发 现 这 个 数 小 于 m i d 就 赶 快 拿 下 来 那么我们从索引1开始往后看,一旦发现这个数小于mid就赶快拿下来 那么我们从索引1开始往后看,一旦发现这个数小于mid就赶快拿下来
这 个 索 引 拿 了 给 奇 数 索 引 , 下 一 个 数 就 马 上 给 偶 数 索 引 , 这 样 让 后 面 奇 数 的 选 择 更 多 这个索引拿了给奇数索引,下一个数就马上给偶数索引,这样让后面奇数的选择更多 这个索引拿了给奇数索引,下一个数就马上给偶数索引,这样让后面奇数的选择更多
不 管 那 个 数 多 么 小 都 给 偶 数 索 引 , 因 为 相 邻 的 两 个 小 数 肯 定 只 能 拿 一 个 不管那个数多么小都给偶数索引,因为相邻的两个小数肯定只能拿一个 不管那个数多么小都给偶数索引,因为相邻的两个小数肯定只能拿一个
因 为 贡 献 相 同 , 肯 定 拿 前 面 的 那 个 给 后 面 留 出 更 多 位 置 选 择 因为贡献相同,肯定拿前面的那个给后面留出更多位置选择 因为贡献相同,肯定拿前面的那个给后面留出更多位置选择
结 束 后 , 检 查 选 的 奇 数 索 引 和 偶 数 索 引 是 否 能 达 到 ( k + 1 ) / 2 和 k / 2 结束后,检查选的奇数索引和偶数索引是否能达到(k+1)/2和k/2 结束后,检查选的奇数索引和偶数索引是否能达到(k+1)/2和k/2
Ⅰ . 偶 数 索 引 贡 献 答 案 的 最 小 值 \color{Red}Ⅰ.偶数索引贡献答案的最小值 Ⅰ.偶数索引贡献答案的最小值
因 为 是 偶 数 索 引 , 那 么 第 一 个 数 肯 定 选 给 奇 数 索 引 , 留 给 偶 数 的 选 择 空 间 才 大 因为是偶数索引,那么第一个数肯定选给奇数索引,留给偶数的选择空间才大 因为是偶数索引,那么第一个数肯定选给奇数索引,留给偶数的选择空间才大
剩 下 的 就 和 前 面 一 样 了 , 能 选 就 选 , 选 完 留 给 奇 数 索 引 , 往 下 继 续 选 剩下的就和前面一样了,能选就选,选完留给奇数索引,往下继续选 剩下的就和前面一样了,能选就选,选完留给奇数索引,往下继续选
#include
using namespace std;
const int maxn=2e5+10;
int a[maxn],b[maxn],n,k;
bool isok(int zhi)
{
int ji=0,ou=0;
for(int i=1;i<=n;i++)//奇数情况
if(a[i]<=zhi)
{
ji++,i++;
if(i<=n) ou++;
}
if(ji>=(k+1)/2&&ou>=k/2) return true;
ji=1,ou=0;
for(int i=2;i<=n;i++)//偶数情况
if(a[i]<=zhi)
{
ou++,i++;
if(i<=n) ji++;
}
if(ji>=(k+1)/2&&ou>=k/2) return true;
return false;
}
int main()
{
cin >> n >> k;
for(int i=1;i<=n;i++)
{
cin >> a[i];
b[i]=a[i];
}
sort(b+1,b+1+n);
int l=1,r=n,mid,ans=1e9;
while(r>=l)
{
mid=l+r>>1;
if( isok(b[mid]) ) r=mid-1,ans=b[mid];
else l=mid+1;
}
cout<