首页 > 其他分享 >洛谷P1824 进击的奶牛 题解 二分答案

洛谷P1824 进击的奶牛 题解 二分答案

时间:2023-12-15 19:23:35浏览次数:45  
标签:cnt 洛谷 函数 int 题解 个数 ge P1824 check

题目链接:https://www.luogu.com.cn/problem/P1824

题目大意:

本题相当于在 \(n\) 个数中选 \(c\) 个数,使得这 \(c\) 个数中相差最小的两个数之差尽可能地大。

解题思路:

我们首先可以给 \(a_1 \sim a_n\) 从小到大排一下序(这里有点贪心的思想,你会发现很多涉及贪心的问题在排序之后解决起来都会方便很多)。

然后我们可以开始设计一个 bool check(int x) 函数,用来判断:在任意相邻两个数之差都 \(\ge x\) 的情况下,是否能够选够 \(c\) 个数。

接着咱们就来判断 check(x) 能否成立:

首先,最优解 选 \(a_1\) 肯定没毛病,

假设有一个最优方案,第一个选的数是 \(a_2\),第二个选的数是 \(a_5\),即满足 \(a_5 - a_2 \ge x\),那么 \(a_5 - a_1 \ge x\) 肯定也成立。

在选择了 \(a_1\) 的情况下,我们可以从 \(a_2\) 开始到 \(a_n\) 选剩下来的数,对应前 \(i\) 个数,我肯定是希望尽可能选最多数字,因为这样能够腾给后面的数字的空间就更大。

假设我上一个选择的数是 \(a_p\),对于当前的 \(a_i\) ,若 \(a_i - a_p \ge x\)(相差 \(\ge x\) 了),就选择 \(a_i\),同时更新 \(p\) 为 \(i\)( \(p\) 时刻对应当前最后一个选的数的下标)。

在整个过程中统计一个一共选了多少个数即可,只要 \(\ge c\) 个,check(x) 函数就返回 true;否则,返回 false。

check函数代码:

bool check(int x) {
    int p = 1, cnt = 1; // p表示最近一个选择的点, cnt表示目前已选择的点数
    for (int i = 2; i <= n; i++) {
        if (a[i] - a[p] >= x) {
            p = i;
            cnt++;
        }
    }
    return cnt >= c; // 选够c个就返回true
}

有了 check 函数接下来就是二分答案了。

可以发现,存在一个最大的整数 \(x\),从 \(1\) 到 \(x\) check 函数都会返回 true;从 \(x+1\) 开始 check 函数就都会返回 false 了。

完整代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, c, a[maxn];

bool check(int x) {
    int p = 1, cnt = 1;
    for (int i = 2; i <= n; i++) {
        if (a[i] - a[p] >= x) {
            p = i;
            cnt++;
        }
    }
    return cnt >= c;
}

int main() {
    scanf("%d%d", &n, &c);
    for (int i = 1; i <= n; i++)
        scanf("%d", a+i);
    sort(a+1, a+n+1);
    int l = 0, r = 1e9, res;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid))
            res = mid, l = mid + 1;
        else
            r = mid - 1;
    }
    printf("%d\n", res);
    return 0;
}

标签:cnt,洛谷,函数,int,题解,个数,ge,P1824,check
From: https://www.cnblogs.com/quanjun/p/17904045.html

相关文章

  • ABC332G Not Too Many Balls 题解
    第\(i\)种球有\(a_i\)个,共\(n\)种。第\(i\)种箱子最多共装\(b_i\)个球。共\(m\)种。第\(i\)种球在第\(j\)种箱子里至多放\(ij\)个。问所有箱子放的球数最多是多少。\(1\leqn\leq500,1\leqm\leq5e5,0\leqa_i,b_i\leq1e12\)。很容易建出网络流模型。......
  • CF1784C Monsters (hard version) 题解 线段树
    题目链接:https://codeforces.com/problemset/problem/1784/C题目大意:你面前有\(n\)只怪兽,每只怪兽都有一个初始血量,你可以进行两类操作:操作1:选择任意一个血量大于\(0\)的怪兽,并将它的血量降低\(1\);操作2:将所有存活的怪物的血量各自减去\(1\),如果存在怪物的血量恰好降为......
  • PTA-2023第十三次练习题目题解
    PTA-2023第十三次练习题目题解以下代码已做防抄袭处理,切勿抄袭。注意:手机端因为屏幕限制,代码会有(不希望的)换行。解决方案:1.建议使用电脑端打开。2.点击代码进入全屏观看。6-25实验9_5_反向打印字符串思路就是每次先找到字符串的最后一位,然后输出这一位,输出之后将这一位改为‘......
  • P8818 [CSP-S 2022] 策略游戏 题解
    P8818[CSP-S2022]策略游戏题解题目链接P8818[CSP-S2022]策略游戏简化题意小\(A\)先在\(a[l1,r1]\)中选择一个数\(x\),小\(B\)再在\(b[l2,r2]\)中选择一个数\(y\),最后的分数就是\(x\timesy\)。小\(A\)想让分数尽可能地大,而小\(B\)则想让分数尽可能地小......
  • 【问题解决】unable to do port forwarding: socat not found
    问题复现前阵子应公司要求做华为云平台的调研,写了一篇文档包含将华为云CCE下载kuberctl配置及使用kubectl转发流量到本地的操作。今天一早上同事就发来一个错误界面,说是Java远程调试转发过来的端口出现问题,如下图:处理思路最初以为是容器镜像未安装socat所致,安装重新打镜像后......
  • 12月13日80端口被占用问题解决
    在写软件构造作业的时候,发现Jfinal提示java.lang.IllegalStateException:port:80notavailable!原因是因为我们的80端口被占用了,当我们输入localhost的时候出现的是windows iis服务的界面这个时候需要我们关闭windowsiis服务1.点击开始收索服务,在服务界面找到worldWide......
  • luogu1972题解
    还是先写被卡的做法吧。节点的区间用了现用现计算卡常过了。被卡了一上午,难过。话说有人说我码风有点抽象。思路主席树做法。a[i]是贝壳序列。先求出nxt,即与a[i]相同的下一个a[j]的下标j。用p114514[i]记了值为\(i\)的数的下标,循环到序列第\(j\)个数的时候,先......
  • Vue + Element UI 实现复制当前行数据功能(复制到新增页面组件值不能更新等问题解决)
    1、需求使用Vue+ElementUI实现在列表的操作栏新增一个复制按钮,复制当前行的数据可以打开新增弹窗后亦可以跳转到新增页面,本文实现为跳转到新增页面。2、实现1)列表页index.vue<el-table><!--其他列--><el-table-columnlabel="操作"width="150"><templateslot-scope=......
  • [CF980D] Perfect Groups 题解
    [CF980D]PerfectGroups题解思路第一个观察就很难观察到:\[ab=x^2,bc=y^2\Longrightarrow\existz,ac=z^2(a,b,c\ne0)\]证明:两个条件式相乘得到:\[ab^2c=x^2y^2\\ac=\dfrac{x^2y^2}{b^2}(b\ne0)\\\becauseb|x^2,b|y^2\\\thereforeb^2|x^2y^2......
  • P1004 [NOIP2000 提高组] 方格取数 题解
    P1004[NOIP2000提高组]方格取数题解题目链接P1004[NOIP2000提高组]方格取数简要思路注意一下输入可以简化为while(std::cin>>x>>y>>val&&x){ //***}运用DP的思想。用一个四维的\(DP\)数组\(dp[i][j][k][l]\)来同时记录两条路径分别走到\((i,j)\)和\((k,......