Recently Maxim has found an array of n integers, needed by no one. He immediately come up with idea of changing it: he invented positive integer x and decided to add or subtract it from arbitrary array elements. Formally, by applying single operation Maxim chooses integer i (1 ≤ i ≤ n) and replaces the i-th element of array ai either with ai + x or with ai - x. Please note that the operation may be applied more than once to the same position.
Maxim is a curious minimalis, thus he wants to know what is the minimum value that the product of all array elements (i.e. ) can reach, if Maxim would apply no more than k operations to it. Please help him in that.
The first line of the input contains three integers n, k and x (1 ≤ n, k ≤ 200 000, 1 ≤ x ≤ 109) — the number of elements in the array, the maximum number of operations and the number invented by Maxim, respectively.
The second line contains n integers a1, a2, ..., an () — the elements of the array found by Maxim.
Print n integers b1, b2, ..., bn in the only line — the array elements after applying no more than k operations to the array. In particular, should stay true for every 1 ≤ i ≤ n, but the product of all array elements should be minimum possible.
If there are multiple answers, print any of them.
5 3 1 5 4 3 5 2
5 4 3 5 -1
5 3 1 5 4 3 5 5
5 4 0 5 5
5 3 1 5 4 4 5 5
5 1 4 5 5
3 2 7 5 4 2
5 11 -5
题目大意:
一共给你N个数,可以进行k次操作,每次操作可以选择数列中任意一个数,使得其+x或者是-x.
目标是为了使得最终数列的乘积最小,问怎样处理能够达到目的。
思路:
1、假设我们此时有奇数个负数,也就是说此时的序列的乘积是负数的,那么显然我们希望结果最小,那么只要使得这个乘积更小即可。
假设我们此时将序列按照绝对值之后的值从小到大排序之后,我们改变哪个值可以使得乘积减小的贡献值更大呢?显然是对于a【0】的处理,我们将绝对值最小的数,如果他是正数 ,那么增大他,否则减小他,显然可以使得乘积减小的贡献值最大化。
那么对于这部分的处理,我们维护一个优先队列处理K次即可。
2、那么我们接下来分类讨论原序列:
设定cnt表示原序列负数的个数。
①cnt==0.那么就是说原序列的值都是>=0的,那么我们此时找到最小的a【i】.尽可能的将其变成负数,变成负数之后,进入上述有奇数个数负数的处理阶段。如果操作完了也没有将其变成负数,那么输出最终序列即可。
②cnt>0&&cnt%2==1,就是说原序列已经有奇数个负数了,那么直接进入上述奇数个数负数的处理阶段。
③cnt>0&&cnt%2==0,那么我们希望将某一个正数变成负数,或者某一个负数变成整数,以形成奇数个负数的情况,再进入上述奇数个数负数的处理阶段即可。
那么对于这种情况,我们找到绝对值最小的a【i】,如果是正数 ,将其变成负数,否则将其变成正数。
3、注意数据范围,需要使用LL...........
Ac代码(略挫....):
#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll __int64
struct node
{
ll pos,val;
friend bool operator <(node a,node b)
{
return abs(a.val)>abs(b.val);
}
} nod;
ll a[200050];
ll ans[200050];
ll n,m,k;
void Slove()
{
priority_queue<node>s;
for(ll i=0; i<n; i++)
{
nod.pos=i;
nod.val=a[i];
s.push(nod);
}
while(m--)
{
nod=s.top();
s.pop();
if(nod.val<0)
{
nod.val-=k;
}
else nod.val+=k;
s.push(nod);
}
while(!s.empty())
{
nod=s.top();
s.pop();
ans[nod.pos]=nod.val;
}
for(ll i=0; i<n; i++)
{
printf("%I64d ",ans[i]);
}
printf("\n");
}
int main()
{
while(~scanf("%I64d%I64d%I64d",&n,&m,&k))
{
ll cnt=0;
for(ll i=0; i<n; i++)
{
scanf("%I64d",&a[i]);
if(a[i]<0)cnt++;
}
if(cnt==0)
{
ll minn=0x3f3f3f3f,pos;
for(ll i=0;i<n;i++)
{
if(a[i]<minn)
{
minn=a[i];pos=i;
}
}
while(m--)
{
a[pos]-=k;
if(a[pos]<0)break;
}
if(a[pos]<0)Slove();
else
{
for(ll i=0;i<n;i++)
{
printf("%I64d ",a[i]);
}
printf("\n");
}
}
else if(cnt%2==1)
{
Slove();
}
else
{
ll minn=0x3f3f3f3f;
ll pos;
ll zhengfu;
for(ll i=0;i<n;i++)
{
if(abs(a[i])<minn)
{
minn=abs(a[i]);
pos=i;
if(a[i]<0)zhengfu=-1;
else zhengfu=1;
}
}
ll ok=0;
while(m--)
{
if(a[pos]<0)a[pos]+=k;
else a[pos]-=k;
if(zhengfu==1&&a[pos]<0)
{
ok=1;
break;
}
if(zhengfu==-1&&a[pos]>=0)
{
ok=1;
break;
}
}
if(ok==1)Slove();
else
{
for(ll i=0;i<n;i++)
{
printf("%I64d ",a[i]);
}
printf("\n");
}
}
}
}