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 }
优先队列排序情况:
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 }