• Codeforces 1042C Array Product


    题目的大致意思是给一个数组a,大小为n(可能有正数,负数和0可以进行如下两种操作:

    1.选择两个位置i,j(i<j)然后 a[j] *= a[i],把a[i]删除。 i

    2.选择一个位置i,把a[i]删除a[x]

    操作2至多只能用一次。

    最终结果是通过这两个操作,n-1次操作,把数组中的数字处理到只剩一个。并且要求使最后的这个数字尽量大。

    输出操作的序列。

    1 i j 表示操作1

    2 i 表示操作2

    首先很容易想到是首先把数组中的0和负数给除掉。

    如果有偶数个负数,那就不用管他了,因为几次相乘后是正数

    如果有奇数个负数,那就把负数中最大的负数的位置记下来,用操作2把它删了

    0怎么办呢,无论是奇数个0还是偶数个0,我们都可以通过操作1和操作2把他们给删了。

    同样,我们可以把奇数个负数的情况里面最大的负数同0一起删除。

    这样数组中最后剩下的都是正数了,就可以一个一个的乘了.

    同时我们要考虑到数组全为0的情况,这样最后就不要输出操作2了

    #include<iostream>
    #include<vector>
    using namespace std;const int N = 2e5 + 5;int n,a[N],num,maxn = -2e9,pos,vis[N];
    int main(){
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            if (a[i] == 0) vis[i]=1 ;
            if (a[i] < 0)
            {
                num++;
                if (a[i]>maxn)
                maxn = a[i],pos = i;
            }
        }
        if (num & 1) vis[pos] = 1;//把最大的负数的位置同0一起删除
        int pre = 0,cnt=0;
        for (int i = 1; i <= n; i++)
        {
            if (vis[i])
            {
                if(pre) printf("1 %d %d
    ", pre, i),cnt++;
                pre = i;
            }
        }
        if (pre&&cnt<n-1) printf("2 %d
    ", pre); //cnt防止数组全为0
        pre = 0;
        for (int i = 1; i <= n; i++)
        {
            if (!vis[i])
            {
                if (pre) printf("1 %d %d
    ", pre, i);
                pre = i;
            }
        }
        return 0;
    }

    (1

  • 相关阅读:
    Beans
    Redis记录-Redis命令
    Redis记录-Redis介绍
    RESTful记录-RESTful服务
    RESTful记录-RESTful内容
    RESTful记录-RESTful介绍
    HTTP记录-HTTP介绍
    Solr记录-solr检索和查询数据
    Solr记录-solr文档xml
    Solr记录-solr内核与索引
  • 原文地址:https://www.cnblogs.com/xiaoguapi/p/10446235.html
Copyright © 2020-2023  润新知