题目描述
小 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.in
与 game/game3.ans
。
【样例 #4】
见附件中的 game/game4.in
与 game/game4.ans
。
【数据范围】
对于所有数据,1≤n,m,q≤1e5,−10e9≤Ai,Bi≤10e9。对于每轮游戏而言,1≤l1≤r1≤n,1≤l2≤r2≤m。
测试点编号 | n,m,q≤ | 特殊条件 |
---|---|---|
1 | 200 | 1, 2 |
2 | 200 | 1 |
3 | 200 | 2 |
4∼5 | 200 | 无 |
6 | 1000 | 1, 2 |
7∼8 | 1000 | 1 |
9∼10 | 1000 | 2 |
11∼12 | 1000 | 无 |
13 | 1e5 | 1, 2 |
14∼15 | 1e5 | 1 |
16∼17 | 1e5 | 2 |
18∼20 | 1e5 | 无 |
其中,特殊性质 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;
}