[20200717NOIP提高组模拟T2]数组

题目大意:

  给你一个长为$n$的数组和$m$次操作机会,每次操作可以选择一个数使其加上或减去$k$,请你求出进行m次操作后得到序列的乘积最小值.

solution:

  此题很明显是贪心,需要努力将所有数的乘积变为负,故消$0$策略:如果当前乘积已为负,则全部变正,否则使最后一个$0$变为负即可.

  若没有$0$可转乘积符号且当前乘积为正,则需找到最接近$0$的数字并努力改变其符号,若操作次数不足以改变符号,则直接出答案.

  $0$全部消去且乘积为负时,需用一个小根堆维护当前序列,堆的键值为序列中每个数的绝对值,然后每次操作将堆顶远离$0$即可.

code:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
long long n,k,x;
long long mod=1000000007;
long long a[1000010];
priority_queue<pair<long long,long long> > q;
int main(){
    scanf("%ld%ld%ld",&n,&k,&x);
    for(long i=1;i<=n;i++)
    scanf("%ld",&a[i]);
    sort(a+1,a+n+1);
    long long cnt=0;
    long long rt=0;
    for(long i=1;i<=n;i++)
    if(a[i]<0) rt++;
    else break;
    if(rt%2==0) rt=2;
    else rt=1;
    long long y,z;
    for(long i=1;i<=n;i++) a[i]=abs(a[i]);
    sort(a+1,a+n+1);
    long sum=1;
    if(x==0 && rt==1) {
        for(long i=1;i<=n;i++)
        sum*=a[i],sum%=mod;
        sum=-sum;
        sum=((sum%mod)+mod)%mod;
    }
    if(x==0 && rt==2) {
        for(long i=1;i<=n;i++)
        sum*=a[i],sum%=mod;
        sum=((sum%mod)+mod)%mod;
    }
    if(a[1]-x*k<=0 && rt==2){
        while(a[1]>0) {
        a[1]=a[1]-x,cnt++;}
        k=k-cnt;
        a[1]=abs(a[1]);
        for(long i=1;i<=n;i++)
        q.push(make_pair(-a[i],i));
        for(long i=1;i<=k;i++)
        {
            y=q.top().second;
            q.pop();
            a[y]+=x;
            q.push(make_pair(-a[y],y));
        }
        
        for(long i=1;i<=n;i++)
        sum*=a[i],sum%=mod;
        sum=-sum;
        sum=((sum%mod)+mod)%mod;
        cout<<sum;
        return 0;
    }
    if(a[1]-x*k>0 && rt==2){
        a[1]=a[1]-x*k;
        for(long i=1;i<=n;i++)
        sum*=a[i],sum%=mod;
        sum=((sum%mod)+mod)%mod;
        cout<<sum;
        return 0;
    }
    if(rt==1){
        for(long i=1;i<=n;i++)
        q.push(make_pair(-a[i],i));
        for(long i=1;i<=k;i++)
        {
            y=q.top().second;
            q.pop();
            a[y]+=x;
            q.push(make_pair(-a[y],y));
        }
        long long sum=1;
        for(long i=1;i<=n;i++)
        sum*=a[i],sum%=mod;
        sum=-sum;
        sum=((sum%mod)+mod)%mod;
        cout<<sum;
        return 0;
    }
    
} 

 

posted @ 2020-07-17 17:13  月落乌啼算钱  阅读(147)  评论(0编辑  收藏  举报