当前位置: 首页 > news >正文

又放学辣(进阶)(两次二分或两次后缀和)(小白80D)

D-又放学辣(进阶)_牛客小白月赛80 (nowcoder.com)

思路:

求最大值的最小值,=》二分;

对于check函数,我们要统计cnt=\sum_{1}^{m}(a[i]-t)的和(t为二分的量),如果cnt<k,说明答案小于t,否则大于t;

时间复杂度为:n*log(n)*log(n)

代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<unordered_map>
#include<map>
using namespace std;
typedef long long LL;
#define  per(i,a,b)  for(int i=a;i<=b;i++) 
const int  N = 1e6 + 100;
int n, k, m, sum, mi;
int  a[N], x, b[N];
int  c[N];
bool cmp(int x, int y)
{
    return x > y;
}
int check(int x, int i)
{   
    int l = 1, r = m, mid, ans = 0, cha;
    while (l <= r)
    {
        mid = (l + r) / 2;
        if (b[mid] >= x)
            ans = mid, l = mid + 1;
        else
            r = mid - 1;
    }
    if (b[ans] <= a[i])
        cha = c[ans] - a[i] - (ans - 1) * x;
    else
        cha = c[ans] - ans * x;
    if (cha <= k||ans==0) return 1;
    return 0;
}
int main()
{
    scanf("%d%d%d", &n, &m, &k);
    per(i, 1, n)
    {
        scanf("%d", &x);
        a[x]++;
    }
    per(i, 1, m) b[i] = a[i];
    sort(b + 1, b + 1 + m, cmp);
    per(i, 1, m) c[i] = c[i - 1] + b[i];
    int l, r, mid;
    per(i, 1, m)
    {
        if (n < k + a[i])
        {
            printf("-1 ");
            continue;
        }
        l = 0;
        r = n - k - a[i];
        mi = -1;
        while (l <= r)
        {
            mid = (l + r) >> 1;
            int y = check(mid, i);
            if (y)
            {
                   r = mid - 1;
                    mi = mid;
            }
            else
                l = mid + 1;
        }
        printf("%d ", mi);
    }
    return 0;
}

思路二:

我们将b[x]代表大于x的总人数;

最开始有一次循环b[a[i]-1]++,表示大于a[i]的数+1;

第一次差分(从后往前):b[i]代表大于i的数有多少个;

第二次差分(从后往前):b[i]代表大于i总共有多少。

代码:

.#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<unordered_map>
#include<map>
using namespace std;
typedef long long LL;
#define per(i,a,b) for(int i=a;i<=b;i++)
#define ber(i,a,b) for(int i=a;i>=b;i--)
const int  N = 1e6 + 100;
int n, k, m, mi;
int  a[N], x, b[N]; 
int check(int x, int i)
{
    int y=b[x];
    if (a[i] > x)
        y -= (a[i] - x);
    return y<=k;
}
int main()
{
    scanf("%d%d%d", &n, &m, &k);
    per(i, 1, n)
    {
        scanf("%d", &x);
        a[x]++;
    }
    per(i, 1,m)
        b[a[i]-1]++;
    ber(i, n, 0)
        b[i] += b[i+1];
    ber(i, n, 0)
        b[i] += b[i+1];
    int l, r, mid;
    per(i, 1, m)
    {
        if (n< k + a[i])
        {
            printf("-1 ");
            continue;
        }
        l = 0;
        r = n - k- a[i];
        mi = -1;
        while (l <= r)
        {
            mid = (l + r) >> 1;
            int y = check(mid, i);
            if (y)
            {
                r = mid - 1;
                mi = mid;
            }
            else
                l = mid + 1;
        }
        if (mi == -1) printf("-1 ");
        else printf("%d ", mi);
    }
    return 0;
}

相关文章:

  • Django实战项目-学习任务系统-用户管理
  • 软件开发全文档归档,开发、管理、实施、运维、服务巡检、信息安全、安全运维
  • Redis测试新手入门教程
  • 美国JASSM-ER(联合防区外空对地导弹-增程型)是
  • 论文阅读——DistilBERT
  • 2.1 ppq量化pytorch->onnx
  • 轻量级 IDE 文本编辑器 Geany 发布 2.0
  • 单元测试到底测什么,怎么测?我来告诉你
  • 计算机网络【CN】介质访问控制
  • c++ pcl 选取点云某一点反馈XYZ坐标的代码
  • [已解决]大数据集群CPU告警问题解决
  • iptables使用示例
  • Stream流
  • AI与Prompt:解锁软件开发团队的魔法咒语,在复杂任务上生成正确率更高的代码
  • 部署vuepress项目到githubPage
  • Android S从桌面点击图标启动APP流程 (五)
  • 通用管理后台项目笔记 - Vue3+Vite安装环境、封装路由
  • el-input输入内容类型为大于0的数字
  • 安防视频监控平台EasyCVR前端解码与后端解码的区别介绍
  • 【MySql】10- 实践篇(八)
  • css用代码做网站/湖南seo服务
  • 做塑料哪个网站好/惠州seo排名
  • iis做网站上传速度慢/网站搜索工具
  • 做网站和做网页有啥区别/网络推广平台排名
  • 电子政务网站模版/百度广告怎么收费标准
  • 组建个人网站/最近国家新闻