CodeForces - 721Dマキシムと配列(貪欲)

最近、マキシムは、配列の発見した  n個の  誰もが必要とする整数を、。彼はすぐにそれを変えるというアイデアを思い付く:彼は正の整数考案  のxを  追加または任意の配列要素からそれを引くことにしました。正式に、マキシムは整数選択単一の操作を適用することによって、  I  (1≤  iは  ≤  nで)と置き換え  Iアレイの番目の要素を  、I  のいずれかで  I  +  X  又は有する  I  -  X操作は同じ位置に複数回適用される場合がありますのでご了承ください。

マキシムは、このように、彼はすべての配列要素(すなわちの製品は、最小値が何であるかを知りたい、好奇心minimalisある  マキシムは以下で適用されないならば、)に達することができる  のkそれに操作を。その中で彼を助けてください。

入力

入力の最初の行は三つの整数含ま  N、  K  及び  X  (1≤  N、  K  200 000、1≤≤  X  ≤10 9配列の要素数、動作の最大数とによって発明番号- )それぞれマキシム、。

2行目は含まれて  、n個の  整数  1、  2、...、  N  (マキシムによって見出さ配列の要素を- )。

出力

プリント  nは  整数  B 1、  B 2、...、  B N  だけラインに-配列要素以下で印加しない後の  k個の  アレイに動作を制御します。具体的には、   すべてのために忠実べき  1≤  iが  ≤  Nが、すべての配列要素の積は、でなければならない  可能最低限。

複数回答がある場合は、それらのいずれかを印刷します。

入力
5 3 1 
5 4 3 5 2
出力
5 4 3 5 -1 
 
アイデア:
数が偶数負の場合、それが奇数になるようにする方法を見つけます。
あなたは、次のステップを変更せずに、奇数になることができない場合。もしそうなら、それだけで奇数になっ制御します。
それ自体が奇数の場合、それはすべての変更を行いません。
 
次に、K-ステップ動作。
現在の負の数が奇数である場合、可能な大型の正の絶対値を作成する方法を見つけるたびに最小絶対値+ xの絶対値とすることができます。
現在の負の数が偶数の場合、絶対の正の和を小さくすることができるようにする方法を見つけ、最小マイナスxの絶対値のそれぞれの絶対値とすることができます。
この操作は、プライオリティキューのメンテナンスを使用しています。
 
______________
(AX)* B = A * B-B * X
明らかに<a優れた際b> B際
 
#include <iostreamの> 
する#include <アルゴリズム> 
の#include <ベクトル> 
の#include <スタック> 
の#include <キュー> 
の#include <地図> 
の#include < セット > 
の#include <cstdioを> 
する#include <CStringの> 
する#include <cmath> 
#include <CTIME> の#defineファック(X)CERR <<#X << "=" << X << ENDL。
#defineデバッグ(X)CERR <<#<< "[" << X << "] =" << [X] << ENDL。
#define LS(T << 1)
 の#define RS((T <<
1)| 1) 使用して名前空間はstdを、
typedefの長い長いです

   LL。
typedefの符号なしの長い 長い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の ダブル EPS = 1E- 6 CONST  ダブル PI = ACOS( - 1 )。

int型N、K。
構造体  ノード{ 
    NUM LL、absnum。
    int型のID。
    ブール 演算子 <(constのノード&P)のconst {
         戻り p.absnum < absnum。
    } 
} [MAXN]。
PRIORITY_QUEUE <ノード> Q。
【MAXN] ANS LL。
int型のmain(){
 //     イオス:: sync_with_stdio(偽);
//     freopenは( "in.txt"、 "R"、STDIN)。

    int型N、K。
    LLのx; 
    scanf関数(" %D%D%LLD "、&​​N&K、&X)
    int型 iは= 1、I ++; iが<= N。){ 
        NUM LL。
        scanf関数(" %のLLD "、&NUM); 
        [I] = ノード{NUM、ABS(NUM)、I}。
    } 
    ソート(A + 1、A + 1個の + N)。
    int型 FU = 0 ;
    int型 iは= 1 ; iが<= N; iが++ ){
         場合([i]が.nu​​m < 0 ){ 
            FU ++ 
        } 
    } 
    もし(fuの%2 == 0 ){
         場合(Xの*のK> =[N] .absnum){
             int型、P =分(1LL * K、[N] .absnum / X + 1 )。
            K - = P。
            もし([N] .nu​​m < 0 ){ 
                [N] .nu​​m + = P * X。
                A [n]は.absnum = ABS([N] .nu​​m)。
            } { 
                [N] .nu​​m - = P *はX。
                A [n]は.absnum = ABS([N] .nu​​m)。
            } 
        } 
    } 
    FU = 0 以下のためのint型 I = 1; iが<= N; iは++ ){
         場合([i]が.nu​​m < 0 ){ 
            FU ++ 
        } 
    } 
    のためのint型 I = 1を iが++; iが<= N ){ 
        q.push([I])。
    } 
    一方(k-- ){ 
        ノードEXA = q.top()。
        q.pop(); 
        もし(FU&1 ){
             場合(exa.num < 0 ){ 
                exa.num - =のX。
                exa.absnum + = X。
            } { 
                exa.num + = X。
                exa.absnum + = X。
            } 
        } {
             場合(exa.num < 0 ){ 
                exa.num + = X。
                exa.absnum - =のX。
            } { 
                exa.num - =のX。
                exa.absnum - =のX。
            } 
        } 
        q.push(EXA)。
    } 
    ながら(!q.empty()){ 
        ノードEXA =q.top(); 
        q.pop(); 
        ANS [exa.id] = exa.num。
    } 
    のためにint型 I = 1を iが++; iが<= N ){ 
        のprintf(" %のLLD " 、ANS [I])。
    } 
    戻り 0 
}
コードの表示

おすすめ

転載: www.cnblogs.com/ZGQblogs/p/11307494.html