CSP-S 2022 策略游戏

· · 题解

考场上花了快一个小时敲了贪心,没想到真拿到了60,回过头来用线段树又敲了一个多小时。。。

考场代码(60PTS)

#include <iostream>
#include <cstdio>
#define MAXN 100001
#define INF 100000000000000000
using namespace std;

long long a[MAXN], b[MAXN]; //L max, Q min

long long findAns(long long l1, long long r1, long long l2, long long r2)
{
    bool z1, f1, z2, f2;
    z1 = f1 = z2 = f2 = false;
    long long maxz1, minz1, maxz2, minz2, maxf1, minf1, maxf2, minf2;
    minz1 = minz2 = minf1 = minf2 = INF;
    maxz1 = maxz2 = maxf1 = maxf2 = -INF;
    for(long long x = l1; x <= r1; x++)
    {
        if(a[x] <= 0)
        {
            f1 = true;
            minf1 = min(minf1, a[x]);
            maxf1 = max(maxf1, a[x]);
        }
        if(a[x] >= 0)
        {
            z1 = true;
            minz1 = min(minz1, a[x]);
            maxz1 = max(maxz1, a[x]);
        }
    }
    for(long long x = l2; x <= r2; x++)
    {
        if(b[x] <= 0)
        {
            f2 = true;
            minf2 = min(minf2, b[x]);
            maxf2 = max(maxf2, b[x]);
        }
        if(b[x] >= 0)
        {
            z2 = true;
            minz2 = min(minz2, b[x]);
            maxz2 = max(maxz2, b[x]);
        }
    }
    if(z1 && f1 && z2 && f2)
    {
        return max(minz1 * minf2, maxf1 * maxz2);
    }
    if(z1 && f1 && z2 && !f2) return maxz1 * minz2;
    if(z1 && f1 && !z2 && f2) return minf1 * maxf2;

    if(z1 && !f1 && z2 && f2) return minz1 * minf2;
    if(z1 && !f1 && z2 && !f2) return maxz1 * minz2;
    if(z1 && !f1 && !z2 && f2) return minz1 * minf2;

    if(!z1 && f1 && z2 && f2) return maxf1 * maxz2;
    if(!z1 && f1 && z2 && !f2) return maxf1 * maxz2;
    if(!z1 && f1 && !z2 && f2) return minf1 * maxf2;

}

int main()
{
    //freopen("game.in", "r", stdin);
    //freopen("game.out", "w", stdout);

    long long n, m, q;
    cin >> n >> m >> q;
    for(long long x = 1; x <= n; x++) cin >> a[x];
    for(long long x = 1; x <= m; x++) cin >> b[x];
    while(q--)
    {
        long long l1, r1, l2, r2;
        cin >> l1 >> r1 >> l2 >> r2;
        cout << findAns(l1, r1, l2, r2) << endl;
    }

    fclose(stdin);
    fclose(stdout);
    return 0;
}

线段树维护正解(AC)

极度优美300行线段树(

#include <iostream>
#include <cstdio>
#define MAXN 400001
#define INF 2147483647
using namespace std;

long long n, m, a[MAXN], b[MAXN]; //L max, Q min
long long taz[MAXN], taf[MAXN], tbz[MAXN], tbf[MAXN];
long long tazm[MAXN], tafm[MAXN], tbzm[MAXN], tbfm[MAXN];

void buildAzMax(long long l, long long r, long long k)
{
    if(l == r)
    {
        if(a[l] >= 0) taz[k] = a[l];
        else taz[k] = -INF;
    }
    else
    {
        long long mid = (l + r) >> 1;
        buildAzMax(l, mid, k<<1);
        buildAzMax(mid+1, r, k<<1|1);
        taz[k] = max(taz[k<<1], taz[k<<1|1]);
    }
}
long long queryAzMax(long long L, long long R, long long l, long long r, long long k)
{
    if(L <= l && r <= R) return taz[k];
    else
    {
        long long re = -INF, mid = (l + r) >> 1;
        if(L <= mid) re = max(re, queryAzMax(L, R, l, mid, k<<1));
        if(R > mid) re = max(re, queryAzMax(L, R, mid+1, r, k<<1|1));
        return re;
    }
}

void buildAzMin(long long l, long long r, long long k)
{
    if(l == r)
    {
        if(a[l] >= 0) tazm[k] = a[l];
        else tazm[k] = INF;
    }
    else
    {
        long long mid = (l + r) >> 1;
        buildAzMin(l, mid, k<<1);
        buildAzMin(mid+1, r, k<<1|1);
        tazm[k] = min(tazm[k<<1], tazm[k<<1|1]);
    }
}
long long queryAzMin(long long L, long long R, long long l, long long r, long long k)
{
    if(L <= l && r <= R) return tazm[k];
    else
    {
        long long re = INF, mid = (l + r) >> 1;
        if(L <= mid) re = min(re, queryAzMin(L, R, l, mid, k<<1));
        if(R > mid) re = min(re, queryAzMin(L, R, mid+1, r, k<<1|1));
        return re;
    }
}

void buildAfMax(long long l, long long r, long long k)
{
    if(l == r)
    {
        if(a[l] <= 0) taf[k] = a[l];
        else taf[k] = -INF;
    }
    else
    {
        long long mid = (l + r) >> 1;
        buildAfMax(l, mid, k<<1);
        buildAfMax(mid+1, r, k<<1|1);
        taf[k] = max(taf[k<<1], taf[k<<1|1]);
    }
}
long long queryAfMax(long long L, long long R, long long l, long long r, long long k)
{
    if(L <= l && r <= R) return taf[k];
    else
    {
        long long re = -INF, mid = (l + r) >> 1;
        if(L <= mid) re = max(re, queryAfMax(L, R, l, mid, k<<1));
        if(R > mid) re = max(re, queryAfMax(L, R, mid+1, r, k<<1|1));
        return re;
    }
}

void buildAfMin(long long l, long long r, long long k)
{
    if(l == r)
    {
        if(a[l] <= 0) tafm[k] = a[l];
        else tafm[k] = INF;
    }
    else
    {
        long long mid = (l + r) >> 1;
        buildAfMin(l, mid, k<<1);
        buildAfMin(mid+1, r, k<<1|1);
        tafm[k] = min(tafm[k<<1], tafm[k<<1|1]);
    }
}
long long queryAfMin(long long L, long long R, long long l, long long r, long long k)
{
    if(L <= l && r <= R) return tafm[k];
    else
    {
        long long re = INF, mid = (l + r) >> 1;
        if(L <= mid) re = min(re, queryAfMin(L, R, l, mid, k<<1));
        if(R > mid) re = min(re, queryAfMin(L, R, mid+1, r, k<<1|1));
        return re;
    }
}

void buildBzMax(long long l, long long r, long long k)
{
    if(l == r)
    {
        if(b[l] >= 0) tbz[k] = b[l];
        else tbz[k] = -INF;
    }
    else
    {
        long long mid = (l + r) >> 1;
        buildBzMax(l, mid, k<<1);
        buildBzMax(mid+1, r, k<<1|1);
        tbz[k] = max(tbz[k<<1], tbz[k<<1|1]);
    }
}
long long queryBzMax(long long L, long long R, long long l, long long r, long long k)
{
    if(L <= l && r <= R) return tbz[k];
    else
    {
        long long re = -INF, mid = (l + r) >> 1;
        if(L <= mid) re = max(re, queryBzMax(L, R, l, mid, k<<1));
        if(R > mid) re = max(re, queryBzMax(L, R, mid+1, r, k<<1|1));
        return re;
    }
}

void buildBzMin(long long l, long long r, long long k)
{
    if(l == r)
    {
        if(b[l] >= 0) tbzm[k] = b[l];
        else tbzm[k] = INF;
    }
    else
    {
        long long mid = (l + r) >> 1;
        buildBzMin(l, mid, k<<1);
        buildBzMin(mid+1, r, k<<1|1);
        tbzm[k] = min(tbzm[k<<1], tbzm[k<<1|1]);
    }
}
long long queryBzMin(long long L, long long R, long long l, long long r, long long k)
{
    if(L <= l && r <= R) return tbzm[k];
    else
    {
        long long re = INF, mid = (l + r) >> 1;
        if(L <= mid) re = min(re, queryBzMin(L, R, l, mid, k<<1));
        if(R > mid) re = min(re, queryBzMin(L, R, mid+1, r, k<<1|1));
        return re;
    }
}

void buildBfMax(long long l, long long r, long long k)
{
    if(l == r)
    {
        if(b[l] <= 0) tbf[k] = b[l];
        else tbf[k] = -INF;
    }
    else
    {
        long long mid = (l + r) >> 1;
        buildBfMax(l, mid, k<<1);
        buildBfMax(mid+1, r, k<<1|1);
        tbf[k] = max(tbf[k<<1], tbf[k<<1|1]);
    }
}
long long queryBfMax(long long L, long long R, long long l, long long r, long long k)
{
    if(L <= l && r <= R) return tbf[k];
    else
    {
        long long re = -INF, mid = (l + r) >> 1;
        if(L <= mid) re = max(re, queryBfMax(L, R, l, mid, k<<1));
        if(R > mid) re = max(re, queryBfMax(L, R, mid+1, r, k<<1|1));
        return re;
    }
}

void buildBfMin(long long l, long long r, long long k)
{
    if(l == r)
    {
        if(b[l] <= 0) tbfm[k] = b[l];
        else tbfm[k] = INF;
    }
    else
    {
        long long mid = (l + r) >> 1;
        buildBfMin(l, mid, k<<1);
        buildBfMin(mid+1, r, k<<1|1);
        tbfm[k] = min(tbfm[k<<1], tbfm[k<<1|1]);
    }
}
long long queryBfMin(long long L, long long R, long long l, long long r, long long k)
{
    if(L <= l && r <= R) return tbfm[k];
    else
    {
        long long re = INF, mid = (l + r) >> 1;
        if(L <= mid) re = min(re, queryBfMin(L, R, l, mid, k<<1));
        if(R > mid) re = min(re, queryBfMin(L, R, mid+1, r, k<<1|1));
        return re;
    }
}

long long findAns(long long l1, long long r1, long long l2, long long r2)
{
    bool z1, f1, z2, f2;
    z1 = f1 = z2 = f2 = false;
    long long maxz1, minz1, maxz2, minz2, maxf1, minf1, maxf2, minf2;
    minz1 = minz2 = minf1 = minf2 = INF;
    maxz1 = maxz2 = maxf1 = maxf2 = -INF;

    maxz1 = queryAzMax(l1, r1, 1, n, 1);
    //cout << "maxz1: " << maxz1 << endl;
    if(maxz1 != -INF) z1 = true;
    minz1 = queryAzMin(l1, r1, 1, n, 1);
    //cout << "minz1: " << minz1 << endl;

    maxf1 = queryAfMax(l1, r1, 1, n, 1);
    //cout << "maxf1: " << maxf1 << endl;
    if(maxf1 != -INF) f1 = true;
    minf1 = queryAfMin(l1, r1, 1, n, 1);
    //cout << "minf1: " << minf1 << endl;

    maxz2 = queryBzMax(l2, r2, 1, m, 1);
    //cout << "maxz1: " << maxz1 << endl;
    if(maxz2 != -INF) z2 = true;
    minz2 = queryBzMin(l2, r2, 1, m, 1);
    //cout << "minz1: " << minz1 << endl;

    maxf2 = queryBfMax(l2, r2, 1, m, 1);
    //cout << "maxf1: " << maxf1 << endl;
    if(maxf2 != -INF) f2 = true;
    minf2 = queryBfMin(l2, r2, 1, m, 1);
    //cout << "minf1: " << minf1 << endl;

    if(z1 && f1 && z2 && f2)
    {
        return max(minz1 * minf2, maxf1 * maxz2);
    }
    if(z1 && f1 && z2 && !f2) return maxz1 * minz2;
    if(z1 && f1 && !z2 && f2) return minf1 * maxf2;

    if(z1 && !f1 && z2 && f2) return minz1 * minf2;
    if(z1 && !f1 && z2 && !f2) return maxz1 * minz2;
    if(z1 && !f1 && !z2 && f2) return minz1 * minf2;

    if(!z1 && f1 && z2 && f2) return maxf1 * maxz2;
    if(!z1 && f1 && z2 && !f2) return maxf1 * maxz2;
    if(!z1 && f1 && !z2 && f2) return minf1 * maxf2;
}

int main()
{
    long long q;
    cin >> n >> m >> q;
    for(long long x = 1; x <= n; x++) cin >> a[x];
    buildAzMax(1, n, 1);
    buildAfMax(1, n, 1);
    buildAzMin(1, n, 1);
    buildAfMin(1, n, 1);
    for(long long x = 1; x <= m; x++) cin >> b[x];
    buildBzMax(1, m, 1);
    buildBfMax(1, m, 1);
    buildBzMin(1, m, 1);
    buildBfMin(1, m, 1);
    while(q--)
    {
        long long l1, r1, l2, r2;
        cin >> l1 >> r1 >> l2 >> r2;
        cout << findAns(l1, r1, l2, r2) << endl;
    }
    return 0;
}