有两种操作
1操作 格式:1 i j 然后把i*j的结果 放在第j个数 第i个数删除
2操作 格式: 2 i 把第i个数删除 且最多只能用一次操作2
题目给你n个数 然后输出这些操作方案 使得n个数最后只剩一个数 这个数需要最大
思路:很容易想到 0的个数 负数的个数 是解题关键
既然是个数 那就有 奇偶 之分
大概都会想到 负数是奇的话 去掉 偶数就直接乘 负负得正嘛
尽可能把0去掉 如何尽可能 进行1操作 我这称为“合0” 然后多个0就会变成一个0了 最后再“去0”
注意奇数是什么 num%2 == 1 那1 也是 但是1个你不能去掉呀 去了就没数了
注意全0 我进行“合0”之后 只剩1个了 这个情况也不能去呀
#include <bits/stdc++.h>
using namespace std;
int main() {
#ifdef _DEBUG
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int n;
scanf("%d", &n);
vector<int> a(n);//vector() 可以动态申请空间
for (int i = 0; i < n; ++i)
scanf("%d", &a[i]);
int cntneg = 0;
int cntzero = 0;
vector<int> used(n);
int pos = -1;
for (int i = 0; i < n; ++i) {
if (a[i] == 0) {
used[i] = 1;
++cntzero;
}
if (a[i] < 0) {
++cntneg;
if (pos == -1 || abs(a[pos]) > abs(a[i]))
pos = i;//保存最大负数
}
}
if (cntneg & 1)//如果负数个数 是奇数
used[pos] = 1;//那么这个奇数也要操作
// 全是0的情况 或 一个负数 其余都是0的情况 合并所有0后 再合并这个负数 变0了
//不用删除
if (cntzero == n || (cntzero == n - 1 && cntneg == 1)) {
for (int i = 0; i < n - 1; ++i)
printf("1 %d %d\n", i + 1, i + 2);
return 0;
}
int lst = -1;
for (int i = 0; i < n; ++i) {
if (used[i]) {
if (lst != -1) printf("1 %d %d\n", lst + 1, i + 1);
lst = i;//找到两个才输出
}
}
if (lst != -1) printf("2 %d\n", lst + 1);//最后还要删除0 和 最大负数的产物
//然后就是剩下的数 操作1
lst = -1;
for (int i = 0; i < n; ++i) {
if (!used[i]) {
if (lst != -1) printf("1 %d %d\n", lst + 1, i + 1);
lst = i;
}
}
return 0;
}