目录
一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
二、解题报告
1、思路分析
2、复杂度
3、代码详解
一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
Problem - 721D - Codeforces
二、解题报告
1、思路分析
如果我们当前乘积为正,那么我们首先要将乘积调整到非正(注意不一定是负)再继续求解,这一步很好想,找到绝对值最小的元素将其调整变号即可(注意变号有可能是变为0,为什么调整到0和后面的策略有关)
我们最终的结果有两种情况,正值/非正值
-
结果是正数的情况
- 初值为正,使绝对值最小数变号所需次数不够,那我们只能使得最后结果是正的。我们发现将绝对值最小的数变号即调整到0最优。否则,如果我们将a、b(a < b)两个元素分别操作ka、kb次,那么(a - ka * x)(b - kb * x) = ab - bka * x - akb * x + ka * kb * x^2 >= ab - b ka * x - bkb * x = b * (a - (ka + kb) * x),故得证。所以当无法调整变号时,我们调整绝对值最小的数是最优的
-
结果是负数的情况
- 调整完后,我们整体乘积应该是小于等于0的
- 我们先考虑小于0了已经,那么剩下元素该如何调整呢?——每次操作应当选择绝对值最小的进行操作,因为一次操作后的乘积和操作前的乘积比值为|a| + x / |a|,显然|a|越小越好
- 现在来考虑0,原数组中是有一部分0的,我们应该对0/1 个0进行-x操作,剩下的0进行+x操作,如果不懂可以看代码理解,这个不好叙述
2、复杂度
时间复杂度: O(nlogn)空间复杂度:O(n)
3、代码详解
import heapq
import sysn, k, x = map(int, input().split())
nums = list(map(int, input().split()))neg = sum(1 for a in nums if a < 0) & 1if not neg:mi = 0for i in range(n):if abs(nums[i]) < abs(nums[mi]):mi = idec = (abs(nums[mi]) - 1) // x + 1if k < dec:nums[mi] += k * x if nums[mi] < 0 else k * -xprint(' '.join(map(str, nums)))exit()if nums[mi] < 0:neg = Truek -= decnums[mi] += dec * x if nums[mi] < 0 else dec * -xpq = [abs(nums[i]) * n + i for i in range(n)]
heapq.heapify(pq)
for _ in range(k):i = heapq.heappop(pq) % nif nums[i] == 0 and not neg:nums[i] -= xneg = Trueelse:nums[i] += x if nums[i] >= 0 else -xheapq.heappush(pq, abs(nums[i]) * n + i)
print(' '.join(map(str, nums)))