P8818 [CSP-S 2022] 策略游戏 题解
思路#
题意:求一个特定矩形中每一行的最小值的最大值。
考虑分类讨论。
注意,由于
-
全部都是正的。由于
全部都是正的。那么无论小L选择什么,小Q总是会选择
序列中最小值。所以小L只需要从最大值(小Q选的是正数)和最小值(小Q选的是负数)中选一个就可以了。
-
全部都是负的。与第一点类似。
由于
全部都是负的。那么无论小L选择什么,小Q总是会选择
序列中最大值。所以小L只需要从最大值(小Q选的是负数)和最小值(小Q选的是正数)中选一个就可以了。
-
全部都是正的由于我们已经考虑了上面两点,所以现在
序列必然是既有正数又有负数。那么小L一定会选择最大值,小Q也一定会选择最小值。
-
全部都是负的和上面类似,其实就是反过来
那么小L一定会选择最小值,小Q也一定会选择最大值。
-
没有特殊限制
考虑到两个序列都是既有正数又有负数。
那么就可以发现如果小L选择的是一个负数,那么小Q就会选择最大值;如果小L选择的是一个正数,那么小Q就会选择最小值。
所以小L一定会选择最接近零的正数和负数,也就是正数最小值和负数最大值。
考虑一下上面需要求的东西。
这个开四颗线段树就可以了。
时间复杂度
代码也比较好写。
Code#
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100010;
int n , m , q , a[N] , b[N];
int s[N] , sum1[N] , sum2[N] , sum3[N] , sum4[N];
struct Node
{
int l , r , minn , maxx;
};
struct Tree
{
Node t[N * 4];
inline void push_up(int p)
{
t[p].minn = min(t[p * 2].minn , t[p * 2 + 1].minn);
t[p].maxx = max(t[p * 2].maxx , t[p * 2 + 1].maxx);
}
inline void build(int p , int l , int r)
{
t[p].l = l , t[p].r = r;
if(l == r) return t[p].minn = t[p].maxx = s[l] , void();
int mid = (l + r) / 2;
build(p * 2 , l , mid);
build(p * 2 + 1 , mid + 1 , r);
push_up(p);
}
inline int ask1(int p , int l , int r)
{
if(l <= t[p].l && t[p].r <= r)
return t[p].minn;
int mid = (t[p].l + t[p].r) / 2 , ans = 1e9;
if(l <= mid) ans = min(ans , ask1(p * 2 , l , r));
if(r > mid) ans = min(ans , ask1(p * 2 + 1 , l , r));
return ans;
}
inline int ask2(int p , int l , int r)
{
if(l <= t[p].l && t[p].r <= r)
return t[p].maxx;
int mid = (t[p].l + t[p].r) / 2 , ans = -1e9;
if(l <= mid) ans = max(ans , ask2(p * 2 , l , r));
if(r > mid) ans = max(ans , ask2(p * 2 + 1 , l , r));
return ans;
}
}t1 , t2 , t3 , t4;
//t1:a全
//t2:b全
//t3:a正
//t4:a负
inline int read()
{
int asd = 0 , qwe = 1; char zxc;
while(!isdigit(zxc = getchar())) if(zxc == '-') qwe = -1;
while(isdigit(zxc)) asd = asd * 10 + zxc - '0' , zxc = getchar();
return asd * qwe;
}
inline bool ask1(int l , int r) { return (sum1[r] - sum1[l - 1]) == (r - l + 1); }
inline bool ask2(int l , int r) { return (sum2[r] - sum2[l - 1]) == (r - l + 1); }
inline bool ask3(int l , int r) { return (sum3[r] - sum3[l - 1]) == (r - l + 1); }
inline bool ask4(int l , int r) { return (sum4[r] - sum4[l - 1]) == (r - l + 1); }
signed main()
{
n = read() , m = read() , q = read();
for(int i = 1;i <= n;i++)
a[i] = read();
for(int i = 1;i <= m;i++)
b[i] = read();
for(int i = 1;i <= n;i++)
s[i] = a[i] , sum1[i] = sum1[i - 1] + (a[i] <= 0) , sum3[i] = sum3[i - 1] + (a[i] >= 0);
t1.build(1 , 1 , n);
for(int i = 1;i <= m;i++)
s[i] = b[i] , sum2[i] = sum2[i - 1] + (b[i] <= 0) , sum4[i] = sum4[i - 1] + (b[i] >= 0);
t2.build(1 , 1 , m);
for(int i = 1;i <= n;i++) s[i] = (a[i] >= 0 ? a[i] : 1e9); t3.build(1 , 1 , n);
for(int i = 1;i <= n;i++) s[i] = (a[i] < 0 ? a[i] : -1e9); t4.build(1 , 1 , n);
for(int i = 1;i <= q;i++)
{
int l1 = read() , r1 = read() , l2 = read() , r2 = read();
if(l1 > r1) swap(l1 , r2); if(l2 > r2) swap(l2 , r2);
if(ask1(l1 , r1))
cout << max(t1.ask2(1 , l1 , r1) * t2.ask2(1 , l2 , r2) , t1.ask1(1 , l1 , r1) * t2.ask2(1 , l2 , r2)) << endl;
else if(ask3(l1 , r1))
cout << max(t1.ask2(1 , l1 , r1) * t2.ask1(1 , l2 , r2) , t1.ask1(1 , l1 , r1) * t2.ask1(1 , l2 , r2)) << endl;
else if(ask2(l2 , r2))
cout << t1.ask1(1 , l1 , r1) * t2.ask2(1 , l2 , r2) << endl;
else if(ask4(l2 , r2))
cout << t1.ask2(1 , l1 , r1) * t2.ask1(1 , l2 , r2) << endl;
else
cout << max(t3.ask1(1 , l1 , r1) * t2.ask1(1 , l2 , r2) , t4.ask2(1 , l1 , r1) * t2.ask2(1 , l2 , r2)) << endl;
}
return 0;
}
作者:JiaY19
出处:https://www.cnblogs.com/JiaY19/p/16847619.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)