2022CSP提高组第二题策略游戏题解

题目描述

小 L 和小 Q 在玩一个策略游戏。

有一个长度为 n 的数组 A 和一个长度为 m 的数组 B,在此基础上定义一个大小为 n×m 的矩阵 C,满足 Cij=Ai×Bj​。所有下标均从 1 开始。

游戏一共会进行 q 轮,在每一轮游戏中,会事先给出 4 个参数 l1,r1,l2,r2​,满足 1≤l1≤r1≤n、1≤l2≤r2≤m。

游戏中,小 L 先选择一个 l1∼r1​ 之间的下标 x,然后小 Q 选择一个 l2∼r2​ 之间的下标 y。定义这一轮游戏中二人的得分是 Cxy。

小 L 的目标是使得这个得分尽可能大,小 Q 的目标是使得这个得分尽可能小。同时两人都是足够聪明的玩家,每次都会采用最优的策略。

请问:按照二人的最优策略,每轮游戏的得分分别是多少?

输入格式

第一行输入三个正整数 n,m,q,分别表示数组 A,数组 B 的长度和游戏轮数。

第二行:n 个整数,表示 Ai,分别表示数组 A 的元素。

第三行:m 个整数,表示 Bi​,分别表示数组 B 的元素。

接下来 q 行,每行四个正整数,表示这一次游戏的 l1,r1,l2,r2l1​,r1​,l2​,r2​。

输出格式

输出共 q 行,每行一个整数,分别表示每一轮游戏中,小 L 和小 Q 在最优策略下的得分。

输入输出样例

输入 #1

3 2 2
0 1 -2
-3 4
1 3 1 2
2 3 2 2

输出 #1

0
4

输入 #2

6 4 5
3 -1 -2 1 2 0
1 2 -1 -3
1 6 1 4
1 5 1 4
1 4 1 2
2 6 3 4
2 5 2 3

输出 #2

0
-2
3
2
-1

说明/提示

【样例解释 #1】

在第一轮游戏中,无论小 L 选取的是 x=2 还是 x=3,小 Q 都有办法选择某个 y 使得最终的得分为负数。因此小 L 选择 x=1 是最优的,因为这样得分一定为 0。

而在第二轮游戏中,由于小 L 可以选 x=2,小 Q 只能选 y=2,如此得分为 4。

【样例 #3】

见附件中的 game/game3.ingame/game3.ans

【样例 #4】

见附件中的 game/game4.ingame/game4.ans

【数据范围】

对于所有数据,1≤n,m,q≤1e5,−10e9≤Ai,Bi≤10e9。对于每轮游戏而言,1≤l1≤r1≤n,1≤l2≤r2≤m。

测试点编号n,m,q≤特殊条件
12001, 2
22001
32002
4∼5200
610001, 2
7∼810001
9∼1010002
11∼121000
131e51, 2
14∼151e51
16∼171e52
18∼201e5

其中,特殊性质 1 为:保证 Ai,Bi>0Ai​,Bi​>0。
特殊性质 2 为:保证对于每轮游戏而言,要么 l1=r1,要么 l2=r2。


题目传送门

这道题搞了一个C矩阵,但是一看数据范围和要求就知道,C矩阵不光没有用,还根本算不了。

所以说这道题大概意思就是A在a数组的l1~r1之间找一个数,B要在b数组l2~r2之间选一个数,如果设A选的数是a[i],b选的数是b[j],则分数为point=a[i]×b[j],A要point大,b让point小

如果b[l1~r1]全都是负数,如果a[l1~r1]有负数,那当然A选最小的,B当然选最大的,如果没有,A依然选最小的,但B要选最小的

如果b[l1~r1]全都是正的,如果a[l1~r1]有正数,那A肯定选最大的,B要选最小的,如果没有,A选最大的,B也要选最大的

如果b[l1~r1]有正有负,那A无论选什么,B都能选一个使point为负,所以A要在绝对值小的里面选,设大于0的最小绝对值为f,小于0的最小绝对值为g,b[l1~r1]中的最小值为minn,最大值为maxn,则最终分数point为max(f×minn,g×maxn)

显然,如果暴力处理的化,复杂度为O(nq),会超时,预计得分60分

所以我们可以采用线段树和ST表,线段树的时间复杂度为O(n+qlogn),ST表为O(nlogn+q),都可以通过

#include <bits/stdc++.h>
using namespace std;
const long long inf = 1e18;
struct Tree {
    long long l,r,minn,maxn,minx,miny;
}tree1[400050],tree2[400050];
long long a[100050],b[100050];
void build1(long long i,long long l,long long r){
    tree1[i].l = l;
    tree1[i].r = r;
    if (l == r){
        tree1[i].minn = a[l];
        tree1[i].maxn = a[l];
        if (a[l] >= 0) tree1[i].minx = a[l],tree1[i].miny = inf;
        if (a[l] < 0) tree1[i].minx = inf,tree1[i].miny = (long long)abs(a[l]);
        return ;
    }
    long long mid = (l + r) >> 1;
    build1(i * 2,l,mid);
    build1(i * 2 + 1,mid + 1,r);
    tree1[i].minn = min(tree1[i * 2].minn,tree1[i * 2 + 1].minn);
    tree1[i].maxn = max(tree1[i * 2].maxn,tree1[i * 2 + 1].maxn);
    tree1[i].minx = min(tree1[i * 2].minx,tree1[i * 2 + 1].minx);
    tree1[i].miny = min(tree1[i * 2].miny,tree1[i * 2 + 1].miny);
}
void build2(long long i,long long l,long long r){
    tree2[i].l = l;
    tree2[i].r = r;
    if (l == r){
        tree2[i].minn = b[l];
        tree2[i].maxn = b[l];
        if (b[l] >= 0) tree2[i].minx = b[l],tree2[i].miny = inf;
        if (b[l] < 0) tree2[i].minx = inf,tree2[i].miny = (long long)abs(b[l]);
        return ;
    }
    long long mid = (l + r) >> 1;
    build2(i * 2,l,mid);
    build2(i * 2 + 1,mid + 1,r);
    tree2[i].minn = min(tree2[i * 2].minn,tree2[i * 2 + 1].minn);
    tree2[i].maxn = max(tree2[i * 2].maxn,tree2[i * 2 + 1].maxn);
    tree2[i].minx = min(tree2[i * 2].minx,tree2[i * 2 + 1].minx);
    tree2[i].miny = min(tree2[i * 2].miny,tree2[i * 2 + 1].miny);
}
long long queryb1(long long i,long long l,long long r){
    if (tree1[i].l > r || tree1[i].r < l) return -inf;
    if (tree1[i].r <= r && tree1[i].l >= l) return tree1[i].maxn;
    long long mid = (tree1[i].l + tree1[i].r) >> 1;
    long long ans = -inf;
    if (l <= mid) ans = max(ans,queryb1(i * 2,l,r));
    if (r > mid) ans = max(ans,queryb1(i * 2 + 1,l,r));
    return ans;
}
long long queryb2(long long i,long long l,long long r){
    if (tree2[i].l > r || tree2[i].r < l) return -inf;
    if (tree2[i].r <= r && tree2[i].l >= l) return tree2[i].maxn;
    long long mid = (tree2[i].l + tree2[i].r) >> 1;
    long long ans = -inf;
    if (l <= mid) ans = max(ans,queryb2(i * 2,l,r));
    if (r > mid) ans = max(ans,queryb2(i * 2 + 1,l,r));
    return ans;
}
long long querys1(long long i,long long l,long long r){
    if (tree1[i].l > r || tree1[i].r < l) return inf;
    if (tree1[i].r <= r && tree1[i].l >= l) return tree1[i].minn;
    long long mid = (tree1[i].l + tree1[i].r) >> 1;
    long long ans = inf;
    if (l <= mid) ans = min(ans,querys1(i * 2,l,r));
    if (r > mid) ans = min(ans,querys1(i * 2 + 1,l,r));
    return ans;
}
long long querys2(long long i,long long l,long long r){
    if (tree2[i].l > r || tree2[i].r < l) return inf;
    if (tree2[i].r <= r && tree2[i].l >= l) return tree2[i].minn;
    long long mid = (tree2[i].l + tree2[i].r) >> 1;
    long long ans = inf;
    if (l <= mid) ans = min(ans,querys2(i * 2,l,r));
    if (r > mid) ans = min(ans,querys2(i * 2 + 1,l,r));
    return ans;
}
long long querys3(long long i,long long l,long long r){
    if (tree1[i].l > r || tree1[i].r < l) return inf;
    if (tree1[i].r <= r && tree1[i].l >= l) return tree1[i].minx;
    long long mid = (tree1[i].l + tree1[i].r) >> 1;
    long long ans = inf;
    if (l <= mid) ans = min(ans,querys3(i * 2,l,r));
    if (r > mid) ans = min(ans,querys3(i * 2 + 1,l,r));
    return ans;
}
long long querys4(long long i,long long l,long long r){
    if (tree2[i].l > r || tree2[i].r < l) return inf;
    if (tree2[i].r <= r && tree2[i].l >= l) return tree2[i].minx;
    long long mid = (tree2[i].l + tree2[i].r) >> 1;
    long long ans = inf;
    if (l <= mid) ans = min(ans,querys4(i * 2,l,r));
    if (r > mid) ans = min(ans,querys4(i * 2 + 1,l,r));
    return ans;
}
long long querys5(long long i,long long l,long long r){
    if (tree1[i].l > r || tree1[i].r < l) return inf;
    if (tree1[i].r <= r && tree1[i].l >= l) return tree1[i].miny;
    long long mid = (tree1[i].l + tree1[i].r) >> 1;
    long long ans = inf;
    if (l <= mid) ans = min(ans,querys5(i * 2,l,r));
    if (r > mid) ans = min(ans,querys5(i * 2 + 1,l,r));
    return ans;
}
long long querys6(long long i,long long l,long long r){
    if (tree2[i].l > r || tree2[i].r < l) return inf;
    if (tree2[i].l >= l && tree2[i].r >= r) return tree2[i].miny;
    long long mid = (tree2[i].l + tree2[i].r) >> 1;
    long long ans = inf;
    if (l <= mid) ans = min(ans,querys6(i * 2,l,r));
    if (r > mid) ans = min(ans,querys6(i * 2 + 1,l,r));
    return ans;
}
long long cnt = 0;
int main(){
    ios :: sync_with_stdio(false);
    //freopen("game.in","r",stdin);
    //freopen("game.out","w",stdout);
    long long n,m;
    long long q;
    cin >> n >> m >> q;
    for (long long i = 1;i <= n;i++) cin >> a[i];
    for (long long i = 1;i <= m;i++) cin >> b[i];
    build1(1,1,n);
    build2(1,1,m);
    while (q--){
        long long l1,r1,l2,r2;
        cin >> l1 >> r1 >> l2 >> r2;
        long long a1 = queryb1(1,l1,r1),a2 = querys1(1,l1,r1),a3 = querys3(1,l1,r1),a4 = -querys5(1,l1,r1);
        long long b1 = queryb2(1,l2,r2),b2 = querys2(1,l2,r2);
        //cout << a1 << " " << a2 << " " << a3 << " " << a4 << endl;
        //cout << b1 << " " << b2 << endl;
        if (b1 < 0){
            if (a2 >= 0) cout << b2 * a2;
            else if (a2 < 0) cout << b1 * a2;
        }
        if (b2 >= 0){
            if (a1 <= 0) cout << a1 * b1;
            if (a1 > 0) cout << a1 * b2;
        }
        if (b1 >= 0 && b2 < 0){
            long long maxn = -inf;
            if (a3 != inf) maxn = max(a3 * b2,maxn);
            if (a4 != -inf) maxn = max(b1 * a4,maxn);
            cout << maxn;
        }
        cout << endl;
    }
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值