codeforces 1042C Array Product【构造】

题目:戳这里

题意:n个数,两种操作,第一种是a[i]*a[j],删掉a[i],第一种是直接删除a[i](只能用一次)剩下的数序列号不变。操作n-1次,使最后剩下的那个数最大化。

解题思路:

正数之间全用操作1得到的结果最大。

负数的个数如果是偶数,全用操作1最后得到的也最大。如果是奇数,那最大的那个负数(贪心的思想)就要进行特殊操作,具体怎么操作要看后面有没有0,如果有0就用操作1去乘,没有就用操作2直接给这个数删了。

有0的话就把所有的0乘最后一个0,然后把最后一个0删了。

附ac代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 5e5 + 10;
 5 const int inf = 5e5 + 10;
 6 struct nod
 7 {
 8     ll a;
 9     int id;
10 }nu[maxn];
11 bool cmp(nod x, nod y)
12 {
13     return x.a < y.a;
14 }
15 int main() {
16     int n;
17     scanf("%d", &n);
18     for(int i = 1; i <= n; ++i)
19     {
20         scanf("%lld", &nu[i].a);
21         nu[i].id = i;
22     }
23     sort(nu + 1, nu + 1 + n, cmp);
24     int cntm = 0;
25     int lastz = 0;
26     int cntop = 0;
27     int firstp = 0;
28     int firstz = 0;
29 
30     for(int i = 1; i <= n; ++i)
31     {
32         if(nu[i].a < 0) ++cntm;
33         if(nu[i].a == 0)
34         {
35            if(!firstz) firstz = i;
36             lastz = i;
37         }
38         if(nu[i].a > 0)
39         {
40             firstp = i;
41             break;
42         }
43     }
44     if(cntm & 1)
45     {
46         if(lastz)   firstz = cntm;
47         else    printf("2 %d\n", nu[cntm].id);
48         --cntm;
49     }
50     for(int i = 1; i < cntm; ++i)
51     {
52         printf("1 %d %d\n", nu[i].id, nu[cntm].id);
53     }
54     for(int i = firstz; i < lastz; ++i)
55     {
56         printf("1 %d %d\n", nu[i].id, nu[i + 1].id);
57     }
58     if(lastz && (cntm || firstp))//这里wa了好多发
59     {
60         printf("2 %d\n", nu[lastz].id);
61 
62     }
63     if(firstp)
64     {
65         if(cntm)
66         {
67             printf("1 %d %d\n", nu[cntm].id, nu[n].id);
68         }
69         for(int i = firstp; i < n; ++i)
70         {
71             printf("1 %d %d\n", nu[i].id, nu[n].id);
72         }
73     }
74     return 0;
75 }
View Code

 

转载于:https://www.cnblogs.com/zmin/p/9671777.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值