错 3 个点求调
查看原帖
错 3 个点求调
487539
LCat90楼主2024/2/23 22:25

Rt。是最后一篇题解的思路。

#include <bits/stdc++.h>
#define int long long
#define pii pair <int, int>
using namespace std;
const int N = 2e5 + 5, Mod = 1e9 + 7, inf = 2e9;
int qkpow(int a, int b) {
	if(!b) return 1;
	if(b & 1) return a * qkpow(a, b - 1) % Mod;
	int t = qkpow(a, b >> 1); return t * t % Mod; 
}
int n, k, a[N], b[N], ans = -inf, sum;
bool cmp(int x, int y) { return abs(x) > abs(y); }
int maxa[N], maxb[N], Mina, Minb; // a : + b : - 
int inv(int x) { return qkpow(x, Mod - 2); }
signed main() {
	cin >> n >> k; bool ff = 1;
	for(int i = 1;i <= n; ++i) {
		cin >> a[i];
		ff &= a[i] < 0;
	} sum = 1;
	if(ff and k & 1) {
		sort(a + 1, a + n + 1);
		for(int i = n;i >= n - k + 1; --i) sum = sum * a[i] % Mod;
		return printf("%lld", (sum + Mod) % Mod), 0;
	} 
	sort(a + 1, a + n + 1, cmp);
	maxa[n + 1] = maxb[n + 1] = -inf;
	Mina = Minb = inf;
	for(int i = 1;i <= k; ++i) {
		sum = a[i] * sum % Mod;
		if(a[i] == 0) return puts("0"), 0;
		if(a[i] > 0) Mina = min(Mina, a[i]);
		else Minb = min(Minb, -a[i]);
	}
	for(int i = n;i > k; --i) {
		if(a[i] == 0) ans = max(ans, 0ll);
		maxa[i] = maxa[i + 1], maxb[i] = maxb[i + 1];
		if(a[i] > 0) maxa[i] = max(maxa[i], a[i]);
		if(a[i] < 0) maxb[i] = max(maxb[i], -a[i]);
	}
	if(sum >= 0) return printf("%lld", sum), 0;
	int x = Mina, y = maxb[k + 1]; // 删正
	ans = max(ans, sum); sum = -sum; 
//	cout << ans << " ";
	if(x != inf and y != -inf) ans = max(ans, sum * y % Mod * inv(x) % Mod);
	x = Minb, y = maxa[k + 1];
	if(x != inf and y != -inf) ans = max(ans, sum * y % Mod * inv(x) % Mod);
//	ans = -44215070; 
	cout << (ans % Mod + Mod) % Mod;
	return 0;
}
/*
首先必须保证是个正数
其实我们的方法是没有问题的

首先按照绝对值排序,计算 premul[k] 
如果 >= 0 则必须是答案 
< 0 调整:(易证得正确性) 
1. - 负 + 正
2. + 负 - 正 
动态维护即可
维护后缀正负数的 abs max 
*/
2024/2/23 22:25
加载中...