• Codeforces Round #374 (Div. 2)-D Maxim and Array


    题目大意:给你n个数,最多有k次操作,每次操作可以将一个任意一个数加上x或者减去x,问你经过k次操作

    之后,满足n个数乘积最小的改变后的序列。

    思路:我们先考虑原序列由奇数个负数,那么我们只要将n个数的绝对值全部加入优先队列,然后每次操作取出

    最小值,如果是负数能减去x,如果是正数加上x,这样进行将会得到最优解。

      再考虑没有负数是偶数个的情况,那么我们如果n个数中的绝对值的最小值小于x*k,则我们将这个绝对值

    最小的数变成反号,然后就变成了第一种情况。 如果n个数中的绝对值的最小值大于等于x*k,如果这个数是正

    数则减去x*k,负数则加上x*k。

    有0的情况需要特殊处理一下,细节比较多,不太好写。

     1 #include<bits/stdc++.h>
     2 #define pii pair<long long,int>
     3 #define mk make_pair
     4 #define fi first
     5 #define se second
     6 #define ll long long
     7 using namespace std;
     8 const int N=2*1e5+5;
     9 int n;
    10 long long a[N],k,x,cnt1=0,cnt2=0;
    11 pii mn,_mn;
    12 priority_queue<pii,vector<pii>,greater<pii> > Q;
    13 int main()
    14 {
    15     mn.fi=1e9+10,_mn.fi=1e9+10;
    16     mn.se=0,_mn.se=0;
    17     scanf("%d%lld%lld",&n,&k,&x);
    18     for(int i=1;i<=n;i++)
    19     {
    20         scanf("%lld",&a[i]);
    21         if(a[i]<0)
    22         {
    23             cnt1++;
    24             _mn=min(_mn,mk(-a[i],i));
    25         }
    26         else if(a[i]>0) mn=min(mn,mk(a[i],i));
    27         else cnt2++;
    28     }
    29     if(cnt2>k)
    30     {
    31         for(int i=1;i<=n;i++) printf("%lld ",a[i]);
    32         return 0;
    33     }
    34     if(cnt2)
    35     {
    36         bool flag=false;
    37         for(int i=1;i<=n;i++)
    38         {
    39             if(a[i]!=0) continue;
    40             if(!(cnt1&1))
    41             {
    42                 a[i]-=x;
    43                 cnt1++;
    44             }
    45             else a[i]+=x;
    46             k--;
    47         }
    48     }
    49     if(!(cnt1&1))
    50     {
    51         ll w=k*x;
    52         if(mn.fi<=_mn.fi)
    53         {
    54             if(mn.fi<w)
    55             {
    56                 cnt1++;
    57                 int u=(mn.fi+1)/x;
    58                 if((mn.fi+1)%x!=0) u++;
    59                 k-=u;
    60                 a[mn.se]-=u*x;
    61             }
    62             else a[mn.se]-=w,k=0;
    63         }
    64         else
    65         {
    66             if(_mn.fi<w)
    67             {
    68                 cnt1--;
    69                 int u=(_mn.fi+1)/x;
    70                 if((_mn.fi+1)%x!=0) u++;
    71                 k-=u;
    72                 a[_mn.se]+=u*x;
    73             }
    74             else a[_mn.se]+=w,k=0;
    75         }
    76     }
    77     if(cnt1&1)
    78     {
    79         for(int i=1;i<=n;i++)
    80         {
    81             if(a[i]==0)
    82             {
    83                 a[i]+=x;
    84                 k--;
    85             }
    86             Q.push(mk(abs(a[i]),i));
    87         }
    88         while(k--)
    89         {
    90             pii cur=Q.top(); Q.pop();
    91             if(a[cur.se]<0) a[cur.se]-=x;
    92             else a[cur.se]+=x;
    93             Q.push(mk(abs(a[cur.se]),cur.se));
    94         }
    95     }
    96     for(int i=1;i<=n;i++) printf("%lld ",a[i]);
    97     puts("");
    98     return 0;
    99 }
    View Code
  • 相关阅读:
    500 多个 Linux 命令文档搜索
    C++ 字符串基本操作
    串的模式匹配算法
    查看、启动、关闭防火墙
    天润融通面试
    LeetCode 169. 求众数
    【面试题】人人车一次面试总结
    一个完整的 JS 身份证校验代码
    oracle多表查询
    百度地图的Icon
  • 原文地址:https://www.cnblogs.com/CJLHY/p/7878650.html
Copyright © 2020-2023  润新知