【题解】CF1042C Array Product【贪心/模拟】

题目大意

给你一个长度为 n n n的整数序列,你可以对其做两种操作:

1 1 1、选 0 &lt; i , j ≤ n , i ̸ = j 0&lt; i,j\le n,i\not= j 0<i,jn,i̸=j,将 a j a_j aj​替换为 a i ⋅ a j a_i\cdot a_j aiaj​,删除 a i a_i ai​。

2 2 2、选一个未被删除的 a i a_i ai​,将其删除。该操作在任意时刻均可执行,最多执行一次。

你需要操作 n − 1 n-1 n1次,剩下一个数,使其最大。由于剩下的数可能会很大,你需要输出得到它的操作序列。

输出任意能得到最大数的操作序列均可。

solution

考虑贪心选取,由于是各个数相乘,考虑有奇数个负数,则负数一定要删去一个。

再考虑 0 0 0的情况,可以把所有的 0 0 0都乘到一起,如果多一个负数,就把负数也乘进来,最终得到答案。

注意只有 n − 1 n-1 n1个操作,对于全零情况,要留一个,不能全删去。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <bitset>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

struct FastIO
{
    inline FastIO& operator >> (int& x) {
        x = 0; char f = 0, ch = getchar();
        while(ch > '9' || ch < '0') f |= (ch == '-'), ch = getchar();
        while(ch <= '9' && ch >= '0') x = x * 10 + ch - 48, ch = getchar();
        return x = (f ? -x : x), *this;
    }
    inline FastIO& operator >> (long long& x) {
        x = 0; char f = 0, ch = getchar();
        while(ch > '9' || ch < '0') f |= (ch == '-'), ch = getchar();
        while(ch <= '9' && ch >= '0') x = x * 10 + ch - 48, ch = getchar();
        return x = (f ? -x : x), *this;
    }
    inline FastIO& operator >> (double& x)
    {
        x = 0; char f = 0, ch = getchar();
        double d = 0.1;
        while(ch > '9' || ch < '0') f |= (ch == '-'), ch = getchar();
        while(ch <= '9' && ch >= '0') x=x * 10 + ch - 48, ch = getchar();
        if(ch == '.')
        {
            ch = getchar();
            while(ch <= '9' && ch >= '0') x += d * (ch ^ 48), d *= 0.1, ch = getchar();
        }
        return x = (f ? -x : x), *this;
    }
}rin;
const int N = 5e5 + 50;
int f[N];
int li, fu;
int vis[N];
vector <int> pos;
int main() {
	int n, cnt = 0;
	rin >> n;
	for(int i = 1 ; i <= n ; ++ i) {
		rin >> f[i];
		if(f[i] == 0) ++ li;
		if(f[i] < 0) ++ fu;
	}
	int del = 0;
	if(fu & 1) {
		int maxn = -(1 << 30);
		for(int i = 1 ; i <= n ; ++ i) {
			if(f[i] < 0) {
				if(maxn < f[i]) {
					maxn = f[i];
					del = i;
				}
			}
		}
		vis[del] = 1;
	}
	if(li) {
		for(int i = 1 ; i <= n ; ++ i) {
			if(f[i] == 0) {
				vis[i] = 1;
				pos.push_back(i);
			}
		}
		if(del) printf("1 %d %d\n", del, pos[0]), ++ cnt;
		for(int i = 1 ; i < pos.size() ; ++ i) printf("1 %d %d\n", pos[i - 1], pos[i]), ++ cnt;
		del = pos[pos.size() - 1];
	}
	int las = 0;
	for(int i = 1 ; i <= n ; ++ i) {
		if(vis[i]) continue;
		las = i;
		break;
	}
	for(int i = las + 1 ; i <= n ; ++ i) {
		if(vis[i]) continue;
		printf("1 %d %d\n", las, i);
		++ cnt;
		las = i;
	}
	if(del != 0 && cnt < n - 1) printf("2 %d\n", del);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值