[CSP-S 2022] 策略游戏 题解

7 篇文章 2 订阅

题面

题目描述

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

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

游戏一共会进行 q q q 轮,在每一轮游戏中,会事先给出 4 4 4 个参数 l 1 , r 1 , l 2 , r 2 l_1, r_1, l_2, r_2 l1,r1,l2,r2,满足 1 ≤ l 1 ≤ r 1 ≤ n 1 \le l_1 \le r_1 \le n 1l1r1n 1 ≤ l 2 ≤ r 2 ≤ m 1 \le l_2 \le r_2 \le m 1l2r2m

游戏中,小 L 先选择一个 l 1 ∼ r 1 l_1 \sim r_1 l1r1 之间的下标 x x x,然后小 Q 选择一个 l 2 ∼ r 2 l_2 \sim r_2 l2r2 之间的下标 y y y。定义这一轮游戏中二人的得分是 C x y C_{x y} Cxy

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

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

输入格式

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

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

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

接下来 q q q 行,每行四个正整数,表示这一次游戏的 l 1 , r 1 , l 2 , r 2 l_1, r_1, l_2, r_2 l1,r1,l2,r2

输出格式

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

样例 #1

样例输入 #1

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

样例输出 #1

0
4

样例 #2

样例输入 #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】

这组数据中,矩阵 C C C 如下:

[ 0 0 − 3 4 6 − 8 ] \begin{bmatrix} 0 & 0 \\ -3 & 4 \\ 6 & -8 \end{bmatrix} 036048

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

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

【数据范围】

对于所有数据, 1 ≤ n , m , q ≤ 10 5 1 \le n, m, q \le {10}^5 1n,m,q105 − 10 9 ≤ A i , B i ≤ 10 9 -{10}^9 \le A_i, B_i \le {10}^9 109Ai,Bi109。对于每轮游戏而言, 1 ≤ l 1 ≤ r 1 ≤ n 1 \le l_1 \le r_1 \le n 1l1r1n 1 ≤ l 2 ≤ r 2 ≤ m 1 \le l_2 \le r_2 \le m 1l2r2m

测试点编号 n , m , q ≤ n, m, q \le n,m,q特殊条件
1 1 1 200 200 2001, 2
2 2 2 200 200 2001
3 3 3 200 200 2002
4 ∼ 5 4 \sim 5 45 200 200 200
6 6 6 1000 1000 10001, 2
7 ∼ 8 7 \sim 8 78 1000 1000 10001
9 ∼ 10 9 \sim 10 910 1000 1000 10002
11 ∼ 12 11 \sim 12 1112 1000 1000 1000
13 13 13 10 5 {10}^5 1051, 2
14 ∼ 15 14 \sim 15 1415 10 5 {10}^5 1051
16 ∼ 17 16 \sim 17 1617 10 5 {10}^5 1052
18 ∼ 20 18 \sim 20 1820 10 5 {10}^5 105

其中,特殊性质 1 为:保证 A i , B i > 0 A_i, B_i > 0 Ai,Bi>0
特殊性质 2 为:保证对于每轮游戏而言,要么 l 1 = r 1 l_1 = r_1 l1=r1,要么 l 2 = r 2 l_2 = r_2 l2=r2

解析

小 Q 的选择

我们先不管小 L ,当小 L 给出了一个 x x x 后,小 Q 一定会选一个 y,使得 A x × B y A_x\times B_y Ax×By 最小。

而当 A x A_x Ax 确定的话,小 Q 的选择只有三种情况:

  1. A x > 0 A_x>0 Ax>0,选择 min ⁡ y = l 2 r 2 B y \min_{y=l_2}^{r_2}B_y y=l2minr2By
  2. A x < 0 A_x<0 Ax<0,选择 max ⁡ y = l 2 r 2 B y \max_{y=l_2}^{r_2}B_y y=l2maxr2By
  3. A x = 0 A_x=0 Ax=0,无论如何选择都是 0。

对于小 Q 而言,他每次只要选择
min ⁡ ( A x × min ⁡ y = l 2 r 2 B y , A x × max ⁡ y = l 2 r 2 B y ) \min(A_x\times\min_{y=l_2}^{r_2}B_y,A_x\times\max_{y=l_2}^{r_2}B_y) min(Ax×y=l2minr2By,Ax×y=l2maxr2By)
这样我们就可以用 ST 表维护 l 2 l_2 l2 ~ r 2 r_2 r2 的最大和最小值,

并成功将小 L 和小 Q 的选择分离开来,使小 L 的选择无法影响到小 Q。

小 L 的选择

然后看小 L,小 L 每次需选择 max ⁡ x = l 1 r 1 ( min ⁡ y = l 2 r 2 ( C x , y ) ) \max_{x=l_1}^{r_1}(\min_{y=l_2}^{r_2}{(C_{x,y})}) x=l1maxr1(y=l2minr2(Cx,y))

如下图:

令红轴( x 轴)为 A,绿轴( y 轴)为 B。
C x , y C_{x,y} Cx,y 为点 ( x , y ) (x,y) (x,y) 在平面投影对应的 z 轴坐标。
由图可知,当 ∣ x ∣ |x| x 越小时 min ⁡ y = l 2 r 2 C x , y \min_{y=l_2}^{r_2}{C_{x,y}} y=l2minr2Cx,y
就越大。
但这还不够,
∀ y , B y ≤ 0 \forall y,B_y\leq 0 y,By0 时易知 A x A_x Ax 取得越小, C x , y C_{x,y} Cx,y 越大;
∀ y , 0 ≤ B y \forall y,0\leq B_y y,0By 时易知 A x A_x Ax 取得越大, C x , y C_{x,y} Cx,y 越大。

所以对于小 L ,我们需要维护4个值。
最大值和最小值同样可以用 ST 表维护,
min ⁡ x = l 1 r 1 ∣ A x ∣ ( 0 ≤ A x ) \min_{x=l_1}^{r_1}{|A_x|}(0\leq A_x) x=l1minr1Ax(0Ax) min ⁡ x = l 1 r 1 ∣ A x ∣ ( A x ≤ 0 ) \min_{x=l_1}^{r_1}{|A_x|}(A_x\leq 0) x=l1minr1Ax(Ax0) 的维护需要考虑是否能用区间合并。
这里证明显然。

总结

用 6 个 ST 表维护:
a 1 = min ⁡ x = l 1 r 1 A x a_1=\min_{x=l_1}^{r_1}{A_x} a1=x=l1minr1Ax
a 2 = max ⁡ x = l 1 r 1 A x a_2=\max_{x=l_1}^{r_1}{A_x} a2=x=l1maxr1Ax
a 3 = min ⁡ x = l 1 r 1 ∣ A x ∣ ( 0 ≤ A x ) a_3=\min_{x=l_1}^{r_1}{|A_x|}(0\leq A_x) a3=x=l1minr1Ax(0Ax)
a 4 = min ⁡ x = l 1 r 1 ∣ A x ∣ ( A x ≤ 0 ) a_4=\min_{x=l_1}^{r_1}{|A_x|}(A_x\leq 0) a4=x=l1minr1Ax(Ax0)
b 1 = min ⁡ y = l 2 r 2 B y b_1=\min_{y=l_2}^{r_2}{B_y} b1=y=l2minr2By
b 2 = max ⁡ y = l 2 r 2 B y b_2=\max_{y=l_2}^{r_2}{B_y} b2=y=l2maxr2By
答案为

max ⁡ i = 1 4 { min ⁡ j = 1 2 ( a i × b j ) } \max_{i=1}^{4}\{\min_{j=1}^{2}(a_i\times b_j)\} i=1max4{j=1min2(ai×bj)}

代码

赛时代码,极丑

#include<bits/stdc++.h>
using namespace std;
const long long Inf=2000000000;
const int Maxn=100039;
int n,m,q;long long ans;
int L1,R1,L2,R2,k,ks,k2,ks2;
int log2s[Maxn]={0,0,1,1,2}; 
long long A[Maxn],B[Maxn];long long As[5],Bs[3];
long long a[5][Maxn][18],b[3][Maxn][18];
long long Abs(long long a){return a<0?-a:a;}
long long min(long long a,long long b){return a>b?b:a;}
long long max(long long a,long long b){return a>b?a:b;}
long long maxQ(long long a,long long b){
	if(a>=0&&b>=0)
	return a<b?a:b;
	if(a>=0)return a;
	if(b>=0)return b;
	return -Inf;
}
long long minQ(long long a,long long b){
	if(a<=0&&b<=0)
	return a>b?a:b;
	if(b<=0)return b;
	if(a<=0)return a;
	return -Inf;
}
int main(){
 	freopen("game.in","r",stdin);
 	freopen("game.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	register int i,j;
	for(i=4;i<=100000;i++)log2s[i]=log2s[i/2]+1;
	for(i=1;i<=n;i++)scanf("%lld",&A[i]),a[1][i][0]=a[2][i][0]=a[3][i][0]=a[4][i][0]=A[i];
	for(i=1;i<=m;i++)scanf("%lld",&B[i]),b[1][i][0]=b[2][i][0]=B[i];
	for(j=1;(1<<j)<=m;j++){
		for(i=1;i+(1<<j)-1<=m;i++){
			b[1][i][j]=max(b[1][i][j-1],b[1][i+(1<<(j-1))][j-1]);
			b[2][i][j]=min(b[2][i][j-1],b[2][i+(1<<(j-1))][j-1]);
		}
	}for(j=1;(1<<j)<=n;j++){
		for(i=1;i+(1<<j)-1<=n;i++){
			a[1][i][j]=max(a[1][i][j-1],a[1][i+(1<<(j-1))][j-1]);
			a[2][i][j]=min(a[2][i][j-1],a[2][i+(1<<(j-1))][j-1]);
			a[3][i][j]=maxQ(a[3][i][j-1],a[3][i+(1<<(j-1))][j-1]);
			a[4][i][j]=minQ(a[4][i][j-1],a[4][i+(1<<(j-1))][j-1]);
		}
	}
	while(q--){
		scanf("%d%d%d%d",&L1,&R1,&L2,&R2);
		k=log2s[R2-L2+1],k2=log2s[R1-L1+1];
		ks=(1<<k),ks2=(1<<k2);
		Bs[1]=max(b[1][L2][k],b[1][R2-ks+1][k]);
		Bs[2]=min(b[2][L2][k],b[2][R2-ks+1][k]);
		As[1]=max(a[1][L1][k2],a[1][R1-ks2+1][k2]);
		As[2]=min(a[2][L1][k2],a[2][R1-ks2+1][k2]);
		As[3]=maxQ(a[3][L1][k2],a[3][R1-ks2+1][k2]);
		As[4]=minQ(a[4][L1][k2],a[4][R1-ks2+1][k2]);
		ans=max(min(As[1]*Bs[1],As[1]*Bs[2]),min(As[2]*Bs[1],As[2]*Bs[2]));
		if(As[3]!=-Inf)ans=max(ans,min(As[3]*Bs[1],As[3]*Bs[2]));
		if(As[4]!=-Inf)ans=max(ans,min(As[4]*Bs[1],As[4]*Bs[2]));
		printf("%lld\n",ans);
	}
	return 0;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值