Заметим, что произведение элементов массива будет меньше, если оно будет отрицательным. А чтобы произведение метрик было отрицательным, среди значений не должно быть 0 и количество отрицательных метрик должно быть нечетным.
Будем действовать следующим образом, жадно улучшая результат на каждом шаге.
Если среди значений метрик есть нули, будем прибавлять или вычитать d из метрики, равной нулю. При этом необходимо поддерживать количество отрицательных значений нечетным. Если количество нулей больше k, то мы никак не можем получить результат, отличный от нуля, и любая последовательность действий будет правильным ответом. Иначе, чтобы получить отрицательное произведение, надо изменить каждый ноль как минимум один раз (и при этом мы всегда можем получить отрицательное произведение).
Если текущее произведение метрик положительное, то мы хотим изменить знак значения одной метрики. В качестве такого числа надо брать наименьшее по модулю. Предположим, что у нас есть две метрики: x и y, |x| < |y|. Докажем, что менять знак y невыгодно. Пусть m — минимальное число операций, необходимое для изменения знака y. Если мы применим m операций к y, то модуль x не изменится, а модуль y станет равен d × m − |y|. Если же мы применим m операций к x, то модуль числа x станет равен d × m − |x|, модуль y не изменится. После проделанных операций произведение будет отрицательным, поэтому необходимо максимизировать произведение модулей.
|y| × (d × m − |x|) > |x| × (d × m − |y|), так как |y| > |x| и d × m − |x| > d × m − |y|.
После того как произведение метрик стало отрицательным, следует выбирать минимальное по модулю число и увеличивать его модуль. Пусть есть две метрики со значениями x, y и еще сколько-то метрик с отрицательным произведением p. Если |x| < |y|, то (|x| + d) × |y| · p < |x| × (|y| + d) × p. Таким образом, выгодно увеличивать (или уменьшать, когда она отрицательная) метрику с минимальным значением по модулю.
Будем повторять описанную выше операцию до тех пор, пока мы не исчерпаем лимит в k изменений. Для быстрого поиска элемента с минимальным модулем следует использовать приоритетную очередь (priority_queue в C++) или множество (set) на основе дерева поиска. Тогда время работы решения будет O (n + m log n).