1 条题解
-
4
由于数值有正有负,所以需要分类讨论。
- 第一个人拿非负数的 ,则第二个人为了乘积小,必须拿负数的
- 第一个人拿非负数的 ,则第二个人为了乘积小,必须拿负数的
- 第一个人拿负数的 ,则第二个人为了乘积小,必须拿正数的
- 第一个人拿负数的 ,则第二个人为了乘积小,必须拿正数的
故而我们需要维护两个序列的非负数 以及负数的
其实再细分一下可以少一些情况,这里留给读者思考吧,每个数列需要维护四个区间静态最值,一共要维护 个,笔者采用维护 个 ST 表,然后分类求解,分类时需要特判如果这个区间就不存在负数或非负数等情况
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1e5 + 5; ll n, m, a[N], b[N], q; ll fmxa[N][17], fmna[N][17], gmxa[N][17], gmna[N][17]; ll fmxb[N][17], fmnb[N][17], gmxb[N][17], gmnb[N][17]; void init() { for (int i = 1; i <= n; i++) { if (a[i] >= 0) { fmxa[i][0] = fmna[i][0] = a[i]; gmxa[i][0] = -1e9, gmna[i][0] = 1e9; } else { fmxa[i][0] = -1e9, fmna[i][0] = 1e9; gmxa[i][0] = gmna[i][0] = a[i]; } } for (int i = 1; i <= m; i++) { if (b[i] >= 0) { fmxb[i][0] = fmnb[i][0] = b[i]; gmxb[i][0] = -1e9, gmnb[i][0] = 1e9; } else { fmxb[i][0] = -1e9, fmnb[i][0] = 1e9; gmxb[i][0] = gmnb[i][0] = b[i]; } } for (int j = 1; (1 << j) <= n; j++) { for (int i = 1; i + (1 << j) - 1 <= n; i++) { fmxa[i][j] = max(fmxa[i][j - 1], fmxa[i + (1 << (j - 1))][j - 1]); gmxa[i][j] = max(gmxa[i][j - 1], gmxa[i + (1 << (j - 1))][j - 1]); fmna[i][j] = min(fmna[i][j - 1], fmna[i + (1 << (j - 1))][j - 1]); gmna[i][j] = min(gmna[i][j - 1], gmna[i + (1 << (j - 1))][j - 1]); } } for (int j = 1; (1 << j) <= m; j++) { for (int i = 1; i + (1 << j) - 1 <= m; i++) { fmxb[i][j] = max(fmxb[i][j - 1], fmxb[i + (1 << (j - 1))][j - 1]); gmxb[i][j] = max(gmxb[i][j - 1], gmxb[i + (1 << (j - 1))][j - 1]); fmnb[i][j] = min(fmnb[i][j - 1], fmnb[i + (1 << (j - 1))][j - 1]); gmnb[i][j] = min(gmnb[i][j - 1], gmnb[i + (1 << (j - 1))][j - 1]); } } } int queryfmxa(int l, int r)// a 正数的max { int k = log2(r - l + 1); return max(fmxa[l][k], fmxa[r - (1 << k) + 1][k]); } int queryfmna(int l, int r)// a 正数的min { int k = log2(r - l + 1); return min(fmna[l][k], fmna[r - (1 << k) + 1][k]); } int queryfmxb(int l, int r)// b 正数的max { int k = log2(r - l + 1); return max(fmxb[l][k], fmxb[r - (1 << k) + 1][k]); } int queryfmnb(int l, int r)// b 正数的min { int k = log2(r - l + 1); return min(fmnb[l][k], fmnb[r - (1 << k) + 1][k]); } int querygmxa(int l, int r)// a 负数的max { int k = log2(r - l + 1); return max(gmxa[l][k], gmxa[r - (1 << k) + 1][k]); } int querygmna(int l, int r)// a 负数的min { int k = log2(r - l + 1); return min(gmna[l][k], gmna[r - (1 << k) + 1][k]); } int querygmxb(int l, int r)// b 负数的max { int k = log2(r - l + 1); return max(gmxb[l][k], gmxb[r - (1 << k) + 1][k]); } int querygmnb(int l, int r)// b 负数的min { int k = log2(r - l + 1); return min(gmnb[l][k], gmnb[r - (1 << k) + 1][k]); } void debug(int l1, int r1, int l2, int r2) { cout << queryfmxa(l1, r1) << " " << queryfmna(l1, r1) << " " << querygmxa(l1, r1) << " " << querygmna(l1, r1) << "\n"; cout << queryfmxb(l2, r2) << " " << queryfmnb(l2, r2) << " " << querygmxb(l2, r2) << " " << querygmnb(l2, r2) << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m >> q; for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 1; i <= m; i++) cin >> b[i]; init(); while (q--) { int l1, r1, l2, r2; cin >> l1 >> r1 >> l2 >> r2; ll resfmxa = queryfmxa(l1, r1); ll resfmna = queryfmna(l1, r1); ll resgmxa = querygmxa(l1, r1); ll resgmna = querygmna(l1, r1); ll resfmxb = queryfmxb(l2, r2); ll resfmnb = queryfmnb(l2, r2); ll resgmxb = querygmxb(l2, r2); ll resgmnb = querygmnb(l2, r2); // debug(l1, r1, l2, r2); ll ans = -2e18; if (resfmxa != -1e9) // a在这一段区间有正数 { if (resgmnb != 1e9) // b在这一段区间有负数,选择最小的负数 { ans = max(ans, resfmxa * resgmnb); ans = max(ans, resfmna * resgmnb); } else // b没有负数,则选择正数最小的 { ans = max(ans, resfmxa * resfmnb); ans = max(ans, resfmna * resfmnb); } } if (resgmxa != -1e9) // a在这一段区间有负数 { if (resfmxb != -1e9) // b在这一段有正数,选择最大的正数 { ans = max(ans, resgmxa * resfmxb); ans = max(ans, resgmna * resfmxb); } else // b没有正数 { ans = max(ans, resgmxa * resgmxb); ans = max(ans, resgmna * resgmxb); } } cout << ans << "\n"; } return 0; }
代码长可以使用函数优化
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1e5 + 5; ll n, m, a[N], b[N], q; ll fmxa[N][17], fmna[N][17], gmxa[N][17], gmna[N][17]; ll fmxb[N][17], fmnb[N][17], gmxb[N][17], gmnb[N][17]; void init(ll f[][17], int op, int type, ll a[], int n) { for (int i = 1; i <= n; i++) { if (a[i] >= 0) { if (op == 1) f[i][0] = a[i]; else { if (type == 1) f[i][0] = -1e9; else f[i][0] = 1e9; } } else { if (op == 1) { if (type == 1) f[i][0] = -1e9; else f[i][0] = 1e9; } else f[i][0] = a[i]; } } for (int j = 1; (1 << j) <= n; j++) { for (int i = 1; i + (1 << j) - 1 <= n; i++) { if (type == 1) f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); else f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); } } } ll query(int l, int r, ll f[][17], int op) { int k = log2(r - l + 1); if (op == 1) return min(f[l][k], f[r - (1 << k) + 1][k]); else return max(f[l][k], f[r - (1 << k) + 1][k]); } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m >> q; for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 1; i <= m; i++) cin >> b[i]; init(fmxa, 1, 1, a, n); init(fmna, 1, 2, a, n); init(fmxb, 1, 1, b, m); init(fmnb, 1, 2, b, m); init(gmxa, 2, 1, a, n); init(gmna, 2, 2, a, n); init(gmxb, 2, 1, b, m); init(gmnb, 2, 2, b, m); while (q--) { int l1, r1, l2, r2; cin >> l1 >> r1 >> l2 >> r2; ll resfmxa = query(l1, r1, fmxa, 2); // a数组非负数的max ll resfmna = query(l1, r1, fmna, 1); // a数组非负数的min ll resgmxa = query(l1, r1, gmxa, 2); // a数组负数的max ll resgmna = query(l1, r1, gmna, 1); // a数组负数的min ll resfmxb = query(l2, r2, fmxb, 2); ll resfmnb = query(l2, r2, fmnb, 1); ll resgmxb = query(l2, r2, gmxb, 2); ll resgmnb = query(l2, r2, gmnb, 1); ll ans = -2e18; if (resfmxa != -1e9) // a在这一段区间有正数 { if (resgmnb != 1e9) // b在这一段区间有负数,选择最小的负数 { ans = max(ans, resfmxa * resgmnb); ans = max(ans, resfmna * resgmnb); } else // b没有负数,则选择正数最小的 { ans = max(ans, resfmxa * resfmnb); ans = max(ans, resfmna * resfmnb); } } if (resgmxa != -1e9) // a在这一段区间有负数 { if (resfmxb != -1e9) // b在这一段有正数,选择最大的正数 { ans = max(ans, resgmxa * resfmxb); ans = max(ans, resgmna * resfmxb); } else // b没有正数 { ans = max(ans, resgmxa * resgmxb); ans = max(ans, resgmna * resgmxb); } } cout << ans << "\n"; } return 0; }
- 1
信息
- ID
- 2040
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 90
- 已通过
- 45
- 上传者