rt,比赛的官方数据应该是过了,但是民间数据 WA 了三个点,讨论版和提交记录暂时没有看到类似的错误。
因为不想写分讨,就直接贪心选出可选范围内最大/最小的正负值以及 0,多建了几个 st 表来实现这个思路。
#include <iostream>
#define int long long
using namespace std;
const int MAXN = 1e5 + 7;
int n, m, q, cnt1, cnt2;
int l1, r1, l2, r2;
int aa[MAXN], bb[MAXN], Log[MAXN];
int ax[MAXN], bx[MAXN];
int maxx(int x, int y)
{
if (x * y == 0)
return x + y;
return max(x, y);
}
int minn(int x, int y)
{
if (x * y == 0)
return x + y;
return min(x, y);
}
struct node
{
int nmax, nmin, pmax, pmin, ze;
} a[MAXN][30], b[MAXN][30];
signed main()
{
cin >> n >> m >> q;
Log[0] = -1;
for (int i = 1; i <= n; i ++)
Log[i] = Log[i >> 1] + 1;
for (int i = 1; i <= n; i ++)
{
cin >> aa[i];
if (aa[i] == 0)
a[i][0].ze = 1;
else if (aa[i] > 0)
a[i][0].pmax = a[i][0].pmin = aa[i];
else
a[i][0].nmax = a[i][0].nmin = aa[i];
}
for (int i = 1; i <= m; i ++)
{
cin >> bb[i];
if (bb[i] == 0)
b[i][0].ze = 1;
else if (bb[i] > 0)
b[i][0].pmax = b[i][0].pmin = bb[i];
else
b[i][0].nmax = b[i][0].nmin = bb[i];
}
for (int j = 1; j <= Log[n]; j ++)
for (int i = 1; i + (1 << j) - 1 <= n; i ++)
{
a[i][j].ze = max(a[i][j - 1].ze, a[i + (1 << (j - 1))][j - 1].ze);
a[i][j].nmax = maxx(a[i][j - 1].nmax, a[i + (1 << (j - 1))][j - 1].nmax);
a[i][j].nmin = minn(a[i][j - 1].nmin, a[i + (1 << (j - 1))][j - 1].nmin);
a[i][j].pmax = maxx(a[i][j - 1].pmax, a[i + (1 << (j - 1))][j - 1].pmax);
a[i][j].pmin = minn(a[i][j - 1].pmin, a[i + (1 << (j - 1))][j - 1].pmin);
}
for (int j = 1; j <= Log[m]; j ++)
for (int i = 1; i + (1 << j) - 1 <= m; i ++)
{
b[i][j].ze = max(b[i][j - 1].ze, b[i + (1 << (j - 1))][j - 1].ze);
b[i][j].nmax = maxx(b[i][j - 1].nmax, b[i + (1 << (j - 1))][j - 1].nmax);
b[i][j].nmin = minn(b[i][j - 1].nmin, b[i + (1 << (j - 1))][j - 1].nmin);
b[i][j].pmax = maxx(b[i][j - 1].pmax, b[i + (1 << (j - 1))][j - 1].pmax);
b[i][j].pmin = minn(b[i][j - 1].pmin, b[i + (1 << (j - 1))][j - 1].pmin);
}
while (q --)
{
cnt1 = cnt2 = 0;
cin >> l1 >> r1 >> l2 >> r2;
int ze, nmax, nmin, pmax, pmin, lg, ans = 0;
lg = Log[r1 - l1 + 1];
ze = max(a[l1][lg].ze, a[r1 - (1 << lg) + 1][lg].ze);
nmax = maxx(a[l1][lg].nmax, a[r1 - (1 << lg) + 1][lg].nmax);
nmin = minn(a[l1][lg].nmin, a[r1 - (1 << lg) + 1][lg].nmin);
pmax = maxx(a[l1][lg].pmax, a[r1 - (1 << lg) + 1][lg].pmax);
pmin = minn(a[l1][lg].pmin, a[r1 - (1 << lg) + 1][lg].pmin);
// printf("%d %d %d %d %d %d\n", lg, ze, nmax, nmin, pmax, pmin);
if (ze) ax[++ cnt1] = 0;
if (nmax) ax[++ cnt1] = nmax;
if (nmin) ax[++ cnt1] = nmin;
if (pmax) ax[++ cnt1] = pmax;
if (pmin) ax[++ cnt1] = pmin;
lg = Log[r2 - l2 + 1];
ze = max(b[l2][lg].ze, b[r2 - (1 << lg) + 1][lg].ze);
nmax = maxx(b[l2][lg].nmax, b[r2 - (1 << lg) + 1][lg].nmax);
nmin = minn(b[l2][lg].nmin, b[r2 - (1 << lg) + 1][lg].nmin);
pmax = maxx(b[l2][lg].pmax, b[r2 - (1 << lg) + 1][lg].pmax);
pmin = minn(b[l2][lg].pmin, b[r2 - (1 << lg) + 1][lg].pmin);
// printf("%d %d %d %d %d %d\n", lg, ze, nmax, nmin, pmax, pmin);
if (ze) bx[++ cnt2] = 0;
if (nmax) bx[++ cnt2] = nmax;
if (nmin) bx[++ cnt2] = nmin;
if (pmax) bx[++ cnt2] = pmax;
if (pmin) bx[++ cnt2] = pmin;
// for (int i = 1; i <= cnt1; i ++)
// cout << ax[i] << ' ';
// cout << '\n';
//
// for (int i = 1; i <= cnt2; i ++)
// cout << bx[i] << ' ';
// cout << '\n';
ans = ax[1] * bx[1];
for (int i = 1; i <= cnt1; i ++)
{
int tmp = ax[i] * bx[1];
for (int j = 2; j <= cnt2; j ++)
tmp = min(tmp, ax[i] * bx[j]);
if (i == 1)
ans = tmp;
else
ans = max(ans, tmp);
}
cout << ans << '\n';
}
return 0;
}