Codeforces Round #374 (Div. 2) D. Maxim and Array 贪心+优先队列

题意:

给定 n 个整数,有 k 次机会可以使任意某个数增加或减少 x

问使得最后n个数乘积最小的序列是什么

思路:

首先要想到序列中可能存在负数

负数为负数时:整个序列乘积为负,要是序列乘积更小,我们可以找一个负数-x,也可以找一个正数+x

这时候就要考虑找哪个数:

假设有m个正数,ans = a1*a2*....*am  如果要选择一个数-x,让这个式子变小,我们暴力每一个数的话,可以知道:如果ai 减去x的话,那整个序列相当于减去 x*(ans / ai ) , x ,ans 都是定值,所以要选择ai 尽量小的数;

而本题也可以把这个序列的每个数的绝对值看成上述这个正数式子,无论负数的个数为奇数还是偶数,我们只需要考虑+x 或者-x,但是最优情况一定是选择绝对值最小的数操作

 

具体可以分情况 自己分析一下

 

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <set>

using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
const int maxn = 2e5 + 7;

int n, k, x;
set<P> st;
ll a[maxn];

int main() {
  scanf("%d%d%d", &n, &k, &x);
  int t = 0; // 记录负数个数
  for(int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
    if(a[i] < 0) t ^= 1;
    st.insert(P(abs(a[i]),i));
  }
  for(int i = 0; i < k; ++i) {
    int pos = st.begin()->second;
    st.erase(st.begin());
    if(a[pos] < 0) t ^= 1;
    if(t) a[pos] += x;
    else a[pos] -= x;
    if(a[pos] < 0) t ^= 1;
    st.insert(P(abs(a[pos]),pos));
  }
  for(int i = 1; i <= n; ++i) {
    printf("%lld ", a[i]);
  }

  return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值