Codeforces Round #510 (Div. 2) C. Array Product (codeforces 1042 C)

版权声明:欢迎转载欢迎评论! https://blog.csdn.net/rabbit_ZAR/article/details/82778263

题目:Array Product

题意:
给出一个序列(元素可负,可为0),以及两个操作:
一、合并两个元素,得到的元素在靠后的元素的位置,值为之前两个元素值的乘积。
二、删除一个元素(此操作最多进行一次)。
现要求输出任意一种操作,使得剩余的一个元素的值最大。

思路:
看了很久后可以得到:
一般的,0对答案没有贡献,可以全部删除。
如果负数的个数为偶数,那么这些负数可以全部保留。
如果负数的个数为奇数,那么就删掉最大的负数。
但是只允许删除一次,那么当有多个没有贡献的数时,就将他们先合并,再删除。
注意,当序列中没有相乘可得正数的数时,那么将没有贡献的数合并后所得的数要保留

代码:

#include<bits/stdc++.h>
using namespace std;

#define read(x) scanf("%d",&x);
#define ll long long
#define maxn 200000

int n;
int a[maxn+5];
bool f[maxn+5];

void readin() {
	read(n);
	for(int i=1; i<=n; i++) {
		read(a[i]);
	}
}

vector<int> ans,vec;

int main() {
	readin();
	int flg=0,s=(-(1<<30)),w=0;
	for(int i=1; i<=n; i++) {
		if(a[i]<0) {
			if(a[i]>s) {
				s=a[i];
				w=i;
			}
			flg^=1;
		}
		if(a[i]==0) vec.push_back(i);
	}
	if(flg) {
		vec.push_back(w);
	}
	for(int i=0; i<vec.size(); i++) {
		f[vec[i]]=true;
		if(vec.size()-1==i) {
			if(vec.size()!=n) printf("2 %d\n",vec[i]);
		} else printf("1 %d %d\n",vec[i],vec[vec.size()-1]);
	}
	for(int i=1; i<=n; i++) {
		if(f[i]) continue;
		ans.push_back(i);
	}
	if(ans.size()) for(int i=0; i<ans.size()-1; i++) {
			printf("1 %d %d\n",ans[i],ans[ans.size()-1]);
		}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/rabbit_ZAR/article/details/82778263