题意:
给出一个序列(元素可负,可为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;
}