• [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;
        }
        
    } 
  • 相关阅读:
    php单点登录
    【Docker】docker镜像构建
    【测试经验】网关中间件测试
    【Jmeter】调用Dubbo方法
    【计算机网络】TCP三次握手与四次挥手
    【操作系统】死锁
    【操作系统】线程与进程
    【计算机网络】TCP/IP
    【计算机网络】Http与Https
    【二叉树】二叉树的创建与遍历
  • 原文地址:https://www.cnblogs.com/ylwtsq/p/13331315.html
Copyright © 2020-2023  润新知