CodeForces - 721D 贪心+优先队列(整理一下优先队列排序情况)

题意:

给你一个长度为n的数组,你可以对其中某个元素加上x或者减去x,这种操作你最多只能使用k次,让你输出操作后的数组,且保证这个数组所有元素的乘积尽可能小

 

题解:

在这之前我们要知道a*b>a*(b-x)>(a-x)*b    在a-x>0且b-x>0情况下

 

首先要讨论这n个元素中负数个数有多少个

1、如果负数有奇数个,那么就让绝对值靠近0的数往距离0远点(也就是负数-x,正数+x),这样操作k次后,等到的数组就满足题意

2、如果没有负数,那么首先判断可不可以让一个正数变成负数

2.1、如果可以那么找一个最小的正数变成负数之后(假设这个过程用了y次操作),然后就转化成了问题1,剩下k-y次操作让绝对值靠近0的数往距离0远点

2.2、如果不可以,那就让那个最小的正数尽可能变小

3、负数个数为偶数个,找一个绝对值最小的数,如果这个数是正数,那就把它变成负数(这个时候要看可不可以变成负数,相似于2.1,2.2);如果这个数是负数,那就把它变成正数(这个时候要看可不可以变成正数,相似于2.1,2.2)

 

 

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <math.h>
  5 #include <string.h>
  6 #include <queue>
  7 #include <set>
  8 #include <map>
  9 #include <algorithm>
 10 using namespace std;
 11 const int maxn=2e5+10;
 12 const int inf=0x3f3f3f3f;
 13 const int MAXN = 2e5+10;
 14 typedef long long LL;
 15 struct Node
 16 {
 17     int pos;
 18     LL val;
 19     bool operator < (const Node& that) const
 20     {
 21         return abs(this->val) > abs(that.val);
 22     }
 23 }node[MAXN];
 24 int n;
 25 LL k, x;
 26 
 27 void Solve()
 28 {
 29     priority_queue<Node> que;
 30     for (int i = 1;i <= n;i++)
 31         que.push(node[i]);
 32     while (k)
 33     {
 34         Node now = que.top();
 35         que.pop();
 36         if (now.val >= 0)
 37             now.val += x;
 38         else
 39             now.val -= x;
 40         que.push(now);
 41         k--;
 42     }
 43     while (!que.empty())
 44     {
 45         node[que.top().pos] = que.top();
 46         que.pop();
 47     }
 48     for (int i = 1;i <= n;i++)
 49         printf("%lld ", node[i].val);
 50     printf("\n");
 51 }
 52 
 53 int main()
 54 {
 55     scanf("%d %d %lld", &n, &k, &x);
 56     int cnt = 0;
 57     for (int i = 1;i <= n;i++)
 58     {
 59         scanf("%lld", &node[i].val);
 60         node[i].pos = i;
 61         if (node[i].val < 0)
 62             cnt++;
 63     }
 64     if (cnt == 0)
 65     {
 66         int mpos = 1;
 67         for (int i = 1;i <= n;i++)
 68         {
 69             if (node[i].val < node[mpos].val)
 70                 mpos = i;
 71         }
 72         LL ti = (node[mpos].val+1LL+x-1)/x;
 73         if (ti > k)
 74             node[mpos].val -= k*x;
 75         else
 76             node[mpos].val -= ti*x;
 77         k -= min(ti, k);
 78     }
 79     else if (cnt > 0 && cnt%2 == 0)
 80     {
 81         int mpos = 1;
 82         for (int i = 1;i <= n;i++)
 83         {
 84             if (abs(node[i].val) < abs(node[mpos].val))
 85                 mpos = i;
 86         }
 87         if (node[mpos].val >= 0)
 88         {
 89             LL ti = (node[mpos].val+1LL+x-1)/x;
 90             if (ti > k)
 91                 node[mpos].val -= k*x;
 92             else
 93                 node[mpos].val -= ti*x;
 94             k -= min(ti, k);
 95         }
 96         else
 97         {
 98             LL ti = (abs(node[mpos].val)+1LL+x-1)/x;
 99             if (ti > k)
100                 node[mpos].val += k*x;
101             else
102                 node[mpos].val += ti*x;
103             k -= min(ti, k);
104         }
105     }
106     Solve();
107 
108     return 0;
109 }
View Code

 

 

优先队列排序情况:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int MAXN = 2e5+10;
 5 struct Node
 6 {
 7     int pos;
 8     LL val;
 9     bool operator < (const Node& that) const
10     {
11         return abs(this->val) > abs(that.val);  //这个时候优先队列从小到大排序
12         //return abs(this->val) < abs(that.val);  //这个时候优先队列从大到小排序
13         //return abs(that.val) > abs(this->val);  //这个时候优先队列从大到小排序
14         //return abs(that.val) < abs(this->val);  //这个时候优先队列从小到大排序
15     }
16 }node[MAXN],str1;
17 int main()
18 {
19     priority_queue<Node>r;
20     str1.val=1;
21     r.push(str1);
22     str1.val=2;
23     r.push(str1);
24     str1.val=3;
25     r.push(str1);
26     while(!r.empty())
27         printf("%d ",r.top().val),r.pop();
28     return 0;
29 }

 

posted @ 2020-05-02 11:15  kongbursi  阅读(219)  评论(0编辑  收藏  举报