Codeforces 721D [贪心]

时间:2023-03-09 15:05:33
Codeforces 721D [贪心]
/*
不要低头,不要放弃,不要气馁,不要慌张。
题意:
给一列数a,可以进行k次操作,每次操作可以选取任意一个数加x或者减x,x是固定的数。求如何才能使得这个数列所有数乘积最小。
思路:
贪心...讨论这列数中负数的个数,如果为偶数,那么把数列中绝对值最小的数使其往0的方向前进。
如果为奇数,同样选择绝对值最小的数,使其往背离0的方向前进。
道理很简单...自己写写就看出来了...
wa点:
有一个细节没处理好,如果经过某次操作某个数变成0了...那么我们的负数记录并没有更新...
默认下一次会减...因为我们需要构造一个新的负数...所以这里gg了...
*/ #include<bits/stdc++.h>
#define N 200050
using namespace std;
long long jilu[N];
long long ans[N];
struct st{
st(){}
st(long long a,int aa){
bb=a;
jue=max(a,-a);
id=aa;
}
int id;
long long bb,jue;
};
bool operator < (const st &a,const st &b){
return a.jue<b.jue;
}
multiset<st> ms;
int main()
{
int n,k;
long long x;
int zero=,zheng=,fu=;
scanf("%d%d%lld",&n,&k,&x);
int ddd=;
for(int i=;i<=n;i++){
scanf("%lld",jilu+i);
if(jilu[i]!=-)ddd++;
if(jilu[i]==)zero++;
else if(jilu[i]>)zheng++;
else fu++;
}
for(int i=;i<=n;i++)ms.insert(st(jilu[i],i));
st tmp;
for(int i=;i<=k;i++){
tmp=*ms.begin();
ms.erase(ms.begin());
if(fu%==){
if(tmp.jue<=x)fu++;
if(tmp.bb>=){
tmp.bb-=x;
if(tmp.bb==&&i!=k){
i++;
tmp.bb-=x;
}
}
else{
tmp.bb+=x;
if(tmp.bb==&&i!=k){
tmp.bb+=x;
i++;
}
}
ms.insert(st(tmp.bb,tmp.id));
}
else{
if(tmp.bb>=)tmp.bb+=x;
else tmp.bb-=x;
ms.insert(st(tmp.bb,tmp.id));
}
}
multiset<st>::iterator it;
for(it=ms.begin();it!=ms.end();it++){
ans[it->id]=it->bb;
}
for(int i=;i<=n;i++){
printf("%lld ",ans[i]);
}
}