题目链接: http://codeforces.com/problemset/problem/657/C

--------------------------------------------------------------------------------------------------------

题目的特别之处在于只有 $+1$ $+5$ 这两种操作 我们要考虑如何利用这个条件

多想一下后可以发现 如果最优解的目标值为$x($将至少$k$个人的值增加到$x)$

那么一定存在一个人 他的初始值在 $[x - 4, x]$ 这个范围内

否则将$x$减去$5$后可以得到更优的解

因此可能成为最优解的目标值最多只有 $n * 5$ 种

现在考虑的便是在 $O(n)$ 枚举目标值的前提下 如何对于每个目标值快速计算出答案

我一开始的想法是根据 $mod 5$ 的余数分类 写$5$个数组记录下前缀和什么的

然而这样二分答案有一个 $log$ 二分数组下标又一个 $log$

尽管题目给了 $4s$ 应该可以过 但是总感觉这样做不够优雅

再次分析题目条件我们有可以发现 实际上每次询问都是与目标距离最小的 $k$ 个数 而这个$k$是不变的

于是现在问题就变成了维护一个数据结构 支持查找容器内最小的 $k$个数 以及添加一个数

这显然就是一个堆了 总的复杂度是 $O(n + nlogk)$

由于在 $mod 5$ 的$5$中情况下 所有初始值转移到目标值的代价多少的排序并不是一样的

因此我们维护$5$个堆就好

 #include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 2e5 + ;
const long long inf = 1e9;
int a[N], dis[N * ];
long long sum[];
long long ans = 1e18;
int n, k, b, c, cnt;
priority_queue <long long> q[];
int main()
{
scanf("%d%d%d%d", &n, &k, &b, &c);
b = min(b, c * );
for(int i = ; i <= n; ++i)
{
scanf("%d", &a[i]);
for(int j = ; j < ; ++j)
dis[cnt++] = a[i] + j;
}
sort(a + , a + + n);
sort(dis, dis + cnt);
cnt = unique(dis, dis + cnt) - dis;
int now = ;
for(int i = ; i < cnt; ++i)
{
int x = dis[i], kind =(inf + x) % ;
long long cost;
while(now <= n && a[now] <= x)
{
for(int j = ; j < ; ++j)
{
cost = (inf + j - a[now]) / * b + (inf + j - a[now]) % * c;
q[j].push(cost);
sum[j] += cost;
if((int)q[j].size() > k)
{
sum[j] -= q[j].top();
q[j].pop();
}
}
++now;
}
long long y = (inf + kind - x) / * b * k;
if((int)q[kind].size() == k)
ans = min(ans, sum[kind] - y);
}
printf("%lld\n", ans);
return ;
}

codeforces 657C - Bear and Contribution [想法题]的更多相关文章

  1. Codeforces 639D Bear and Contribution

    Bear and Contribution 对于对于5余数为, 0, 1, 2, 3, 4的分别处理一次, 用优先队列贪心. #include<bits/stdc++.h> #define ...

  2. CodeForces - 156B Suspects 逻辑 线性 想法 题

    题意:有1~N,n(1e5)个嫌疑人,有m个人说真话,每个人的陈述都形如X是凶手,或X不是凶手.现在给出n,m及n个陈述(以+x/-X表示)要求输出每个人说的话是true ,false or notd ...

  3. CodeForces - 798D Mike and distribution 想法题,数学证明

    题意:给你两个数列a,b,你要输出k个下标,使得这些下标对应的a的和大于整个a数列的和的1/2.同时这些下标对应的b //题解:首先将条件换一种说法,就是要取floor(n/2)+1个数使得这些数大于 ...

  4. CodeForces - 55C Pie or die 想法题(猜程序)

    http://codeforces.com/problemset/problem/55/C 题意:一个博弈. 题解:瞎猜,目前不清楚原理 #include<iostream> #inclu ...

  5. codeforces 584E Anton and Ira [想法题]

    题意简述: 给定一个$1$到$n(n<=2000)$的初始排列以及最终排列 我们每次可以选取位置为$i$和$j$的 并交换它们的位置 花费为$ |i-j| $ 求从初始状态变换到末状态所需最小花 ...

  6. codeforces gym 100345I Segment Transformations [想法题]

    题意简述 给定一个由A C G T四个字母组成的密码锁(每拨动一次 A变C C变G G变T T变A) 密码锁有n位 规定每次操作可以选取连续的一段拨动1~3次 问最少几次操作可以将初始状态变到末状态 ...

  7. codeforces 11 B.Jumping Jack 想法题

    B. Jumping Jack Jack is working on his jumping skills recently. Currently he's located at point zero ...

  8. CodeForces 111B - Petya and Divisors 统计..想法题

    找每个数的约数(暴力就够了...1~x^0.5)....看这约数的倍数最后是哪个数...若距离大于了y..统计++...然后将这个约数的最后倍数赋值为当前位置...好叼的想法题.... Program ...

  9. Codeforces 385C Bear and Prime Numbers

    题目链接:Codeforces 385C Bear and Prime Numbers 这题告诉我仅仅有询问没有更新通常是不用线段树的.或者说还有比线段树更简单的方法. 用一个sum数组记录前n项和, ...

随机推荐

  1. C++中的函数重载分析(一)

    1,重载是 C 语言到 C++ 语言的一个飞跃,C 语言中没有重载的概念,所有的函数 名是不允许有重复的,在 C++ 中因为引进了重载,所以函数名可以重复: 2,自然语言中的上下文: 1,你知道上面词 ...

  2. 只使用非递归的mutex

    mutex分为递归(以下简写为rm)和非递归(以下简写为nrm)两种,它们的唯一区别在于:同一个线程可以重复对rm加锁,但是不能重复对nrm加锁. 虽然rm使用起来要更加方便一些,并且不用考虑一个线程 ...

  3. PHP数据结构基本概念

    原文:https://www.cnblogs.com/crystaltu/p/6408484.html 学习任何一种技术都应该先清楚它的基本概念,这是学习任何知识的起点!本文是讲述数据结构的基本概念, ...

  4. 剑指offer-二叉树的下一结点-树-python

    题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针.   思路:中序遍历,pNode节点的下一个节点根据中序 ...

  5. Chrome开发者工具详解(五)之Network面板

    Chrome开发者工具面板 面板上包含了Elements面板.Console面板.Sources面板.Network面板. Timeline面板.Profiles面板.Application面板.Se ...

  6. (新手入门,学习笔记)通过NPM进行Vue.js的安装

    NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,本文只介绍如何通过NPM进行安装Vue.js NodeJS官方网站:http://nodejs.cn/downlo ...

  7. JS 页面跳转,参数的传递

    当我们通过location.replace()进行页面的跳转时,我们想进行参数的传递,当时学习的时候,以前在网上找过获取方法,已经忘记出处在哪里了.获取方法大概是这样的: 1.将参数通过拼接的方式拼接 ...

  8. Docker学习笔记--传送门(持续更新)

    1.ubuntu下安装docker:  https://www.cnblogs.com/salmonLeeson/p/11609699.html 2.为docker配置国内镜像加速器:https:// ...

  9. VMware虚拟机NAT模式无法上外网

    VMware虚拟机NAT模式无法上外网排错思路 1,确保三种模式只有一种在连接 2,确保ip配置正确 配置的子网跟DHCP必须是同一网段 3,确保网关配置正确 网关不管怎么配,一定不要配192.168 ...

  10. 10年前文章_fedora10root登录

    fedora10系统root用户登录以及普通用户使用sudo命令1.问题:fedora10默认不能够直接用root用户登录解决方法:我们可以先以普通用户登录$su#vi /etc/pam.d/gdm删 ...