题目:Array Product
题意:
给出一个序列(元素可负,可为0),以及两个操作:
一、合并两个元素,得到的元素在靠后的元素的位置,值为之前两个元素值的乘积。
二、删除一个元素(此操作最多进行一次)。
现要求输出任意一种操作,使得剩余的一个元素的值最大。
思路:
看了很久后可以得到:
一般的,0对答案没有贡献,可以全部删除。
如果负数的个数为偶数,那么这些负数可以全部保留。
如果负数的个数为奇数,那么就删掉最大的负数。
但是只允许删除一次,那么当有多个没有贡献的数时,就将他们先合并,再删除。
注意,当序列中没有相乘可得正数的数时,那么将没有贡献的数合并后所得的数要保留。
代码:
#include<bits/stdc++.h> using namespace std;#define read(x) scanf("%d",&x); #define ll long long #define maxn 200000int 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; }