CodeForces - 721D Maxim and Array (贪心)

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 koperations to it. Please help him in that.

Input

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.

Output

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.

Examples

Input
5 3 1
5 4 3 5 2
Output
5 4 3 5 -1 
 
思路:
如果负数个数为偶数,想办法让其变成奇数.
如果不能变为奇数,则不做任何变化,进入下一步.如果可以,控制其刚好变为奇数即可.
如果本身就是奇数,则不做任何变化.
 
接下来进行k步操作.
如果当前负数个数为奇数,则想办法使绝对值之积极可能大,每次使绝对值最小的数字的绝对值加上x即可.
如果当前负数个数为偶数,则想办法使绝对值之积极可能小,每次使绝对值最小的数字的绝对值减去x即可.
此操作使用优先队列维护.
 
______________
(a-x) * b = a*b-b*x
显然 当a<b时优于 a>b
 
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>

#define fuck(x) cerr<<#x<<" = "<<x<<endl;
#define debug(a, x) cerr<<#a<<"["<<x<<"] = "<<a[x]<<endl;
#define ls (t<<1)
#define rs ((t<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int loveisblue = 486;
const int maxn = 200086;
const int maxm = 100086;
const int inf = 0x3f3f3f3f;
const ll Inf = 999999999999999999;
const int mod = 1000000007;
const double eps = 1e-6;
const double pi = acos(-1);

int n,k;
struct  node{
    ll num,absnum;
    int id;
    bool operator<(const node &p)const{
        return p.absnum<absnum;
    }
}a[maxn];
priority_queue<node>q;
ll ans[maxn];
int main() {
//    ios::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);

    int n,k;
    ll x;
    scanf("%d%d%lld",&n,&k,&x);
    for(int i=1;i<=n;i++){
        ll num;
        scanf("%lld",&num);
        a[i]=node{num,abs(num),i};
    }
    sort(a+1,a+1+n);
    int fu = 0;
    for(int i=1;i<=n;i++){
        if(a[i].num<0){
            fu++;
        }
    }
    if(fu%2==0){
        if(x*k>=a[n].absnum){
            int p = min(1ll*k,a[n].absnum/x+1);
            k-=p;
            if(a[n].num<0){
                a[n].num+=p*x;
                a[n].absnum = abs(a[n].num);
            }else{
                a[n].num-=p*x;
                a[n].absnum = abs(a[n].num);
            }
        }
    }
    fu = 0;
    for(int i=1;i<=n;i++){
        if(a[i].num<0){
            fu++;
        }
    }
    for(int i=1;i<=n;i++){
        q.push(a[i]);
    }
    while (k--){
        node exa = q.top();
        q.pop();
        if(fu&1){
            if(exa.num<0){
                exa.num-=x;
                exa.absnum+=x;
            }else{
                exa.num+=x;
                exa.absnum+=x;
            }
        }else{
            if(exa.num<0){
                exa.num+=x;
                exa.absnum-=x;
            }else{
                exa.num-=x;
                exa.absnum-=x;
            }
        }
        q.push(exa);
    }
    while (!q.empty()){
        node exa = q.top();
        q.pop();
        ans[exa.id]=exa.num;
    }
    for(int i=1;i<=n;i++){
        printf("%lld ",ans[i]);
    }
    return 0;
}
View Code

转载于:https://www.cnblogs.com/ZGQblogs/p/11307494.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值