• Codeforces G. Nick and Array(贪心)


    题目描述:

    Nick had received an awesome array of integers a=[a1,a2,…,an] as a gift for his 5 birthday from his mother. He was already going to explore its various properties but after unpacking he was disappointed a lot because the product a1⋅a2⋅…an of its elements seemed to him not large enough.

    He was ready to throw out the array, but his mother reassured him. She told him, that array would not be spoiled after the following operation: choose any index i (1≤i≤n) and do ai:=−ai−1.

    For example, he can change array [3,−1,−4,1] to an array [−4,−1,3,1] after applying this operation to elements with indices i=1and i=3.

    Kolya had immediately understood that sometimes it's possible to increase the product of integers of the array a lot. Now he has decided that he wants to get an array with the maximal possible product of integers using only this operation with its elements (possibly zero, one or more times, as many as he wants), it is not forbidden to do this operation several times for the same index.

    Help Kolya and print the array with the maximal possible product of elements a1⋅a2⋅…an which can be received using only this operation in some order.

    If there are multiple answers, print any of them.

    Input

    The first line contains integer n (1≤n≤105) — number of integers in the array.

    The second line contains n integers a1,a2,…,an (−106≤ai≤106) — elements of the array

    Output

    Print n numbers — elements of the array with the maximal possible product of elements which can be received using only this operation in some order from the given array.

    If there are multiple answers, print any of them.

    Examples

    input

    4

    2 2 2 2

    output

    -3 -3 -3 -3

    input

    1

    0

    output

    0

    input

    3

    -3 -3 2

    output

    -3 -3 2

    思路:

    题目是要通过给定的变换,让最后得到的数列的积最大。可以看到正数做了一次变换后绝对值就变大了,负数相反,而且做两次同样的变换相当于没做变换。把所有数都变味负数,如果这个时候元素的个数为偶数,把所有整数变到负数就ok了;如果是奇数个,就想一想该把哪一个负数变成正数乘积最大。

    哪一个呢?首先-1肯定不能乱变,变了就是0。

    刚开始以为是最大的那个数(绝对值最小除了-1外)变成正数,我就先排了个序,还用了什么二分lower_bound,upper_bound,又加个<type>()变成相反地意思,后来发现输出要按顺序,就改写成结构体形式,自己写了一个二分搞得很复杂。

    最后,去的应该是是绝对值最大的元素。-_-||就不用费尽心思把-1挑出去了。

    为什么呢?证明一下:假设0<a1<a2<...<an,a1*a2*...*an的积(忽略符号,a1,a2,...,看成是对应元素的绝对值),现在忽略负号的影响,也就是经过变换现在假设他们只要将一个数做变换成正,最后乘积就是正数的情况下,变a1为a1-1,和变an为an-1哪个大。

    (a1-1)*a2*...*an-a1*a2*...*(an-1)=(a1-an)*(a2*...*a(n-1))<0,也就是变绝对值大的为正数就好了。

    知识点:

     

    1 template <class ForwardIterator, class T, class Compare>
    2 ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,
    3                                const T& val, Compare comp);//自定义比较函数

     

    lower_bound( begin,end,num,greater<type>() ):

    从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

    对应的upper_bound同理(具体见参考文章)

     

    代码:

     

     1 #include <iostream>
     2 #include <algorithm>
     3 #define max_n 100005
     4 using namespace std;
     5 struct node
     6 {
     7     int val;
     8     int ord;
     9 };
    10 node a[max_n];
    11 int n;
    12 int cmp1(node a,node b)
    13 {
    14     return a.val<b.val;
    15 }
    16 int cmp2(node a,node b)
    17 {
    18     return a.ord<b.ord;
    19 }
    20 int bisearch(int num,int l,int r)
    21 {
    22     int mid = 0;
    23     while(l<r)
    24     {
    25         mid = (l+r)>>1;
    26         //cout << l << " " << r << endl;
    27         if(a[mid].val<num)
    28         {
    29             l = mid+1;
    30         }
    31         else //if(a[mid].val>num)
    32         {
    33             r = mid;
    34         }
    35     }
    36     return mid;
    37 }
    38 int main()
    39 {
    40     cin >> n;
    41     for(int i = 0;i<n;i++)
    42     {
    43         cin >> a[i].val;
    44         a[i].ord = i;
    45         if(a[i].val>=0)
    46         {
    47             a[i].val = -a[i].val-1;
    48         }
    49     }
    50     /*for(int i = 0;i<n;i++)
    51     {
    52         cout << a[i].val << " ";
    53     }
    54     cout << endl;*/
    55     if(n%2!=0)
    56     {
    57         sort(a,a+n,cmp1);
    58         a[0].val = -a[0].val-1;
    59         sort(a,a+n,cmp2);
    60         for(int i = 0;i<n;i++)
    61         {
    62             cout << a[i].val << " ";
    63         }
    64         cout << endl;
    65     }
    66     else
    67     {
    68 
    69         for(int i = 0;i<n;i++)
    70         {
    71             cout << a[i].val << " ";
    72         }
    73         cout << endl;
    74     }
    75     return 0;
    76 }

     参考文章:

    讲解lower_bound(虽然这题好像用不上)

    brandong,关于lower_bound( )和upper_bound( )的常见用法,https://blog.csdn.net/qq_40160605/article/details/80150252

    Andywu_0010,lower_bound()函数和upper_bound()函数,以及二分查找,https://i.cnblogs.com/EditPosts.aspx?postid=11249693&update=1

     

  • 相关阅读:
    全新 D 系列虚拟机型号
    D 系列性能预期
    Azure Backup 入门
    对 Azure Backup 的常见配置问题进行故障排除
    宣布发布长期保留 Azure Backup功能
    宣布 Azure Backup 支持备份 Windows Server 2008
    Azure Backup 简介
    MongoDB中ObjectId的误区,以及引起的一系列问题
    UNIX/Linux_C_程序员需要掌握的七种武器
    Docker企业版安装指南
  • 原文地址:https://www.cnblogs.com/zhanhonhao/p/11249693.html
Copyright © 2020-2023  润新知