首页 > 其他分享 >【题解】CSP-S2022 T2策略游戏

【题解】CSP-S2022 T2策略游戏

时间:2022-11-13 14:13:00浏览次数:40  
标签:r1 r2 题解 LL T2 S2022 l1 l2 query

简要题意
有两串数A[1 n],B[1 m]A[1 n],B[1 m],有两个人小L和小QL和小Q,给出q组l1,r1,l2,r2q组l1,r1,l2,r2,对于每组,小L在A[l1 r1]A[l1 r1]中取一数x,小Q在B[l2 r2]B[l2 r2]中取一数y,小L想使xy最大,小Q想使xy最小,求xy

n,m,q<=105n,m,q<=105
算法1
(朴素想法) O(qnlogm)O(qnlogm)
考虑A[l1 r1]A[l1 r1]中每一个数,建一棵线段树(或ST表),再求出最小值,取最小值的最大输出即可
得分:60

C++ 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n,m,q;
LL a[1010],b[1010];
struct xxx{
LL l,r;
LL mn;
}tr[1010][4010];
LL read()
{
LL s=0,w=1;
char ch=getchar();
while('0'>ch||ch>'9')w=ch=='-'?(-w):w,ch=getchar();
while('0'<=ch&&ch<='9')s=s*10+ch-'0',ch=getchar();
return s*w;
}
void write(LL x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
void pushup(LL x,LL u)
{
tr[x][u].mn=min(tr[x][u<<1].mn,tr[x][u<<1|1].mn);
}
void build(LL x,LL u,LL l,LL r)
{
tr[x][u]={l,r};
if(l==r)tr[x][u].mn=a[x]*b[l];
else{
LL mid=l+r>>1;
build(x,u<<1,l,mid),build(x,u<<1|1,mid+1,r);
pushup(x,u);
}
}
LL query(LL x,LL u,LL l,LL r)
{
if(l<=tr[x][u].l&&tr[x][u].r<=r)return tr[x][u].mn;
LL mid=tr[x][u].l+tr[x][u].r>>1,mn=LLONG_MAX;
if(l<=mid)mn=query(x,u<<1,l,r);
if(mid<r)mn=min(mn,query(x,u<<1|1,l,r));
return mn;
}
int main()
{
LL i,j;
n=read(),m=read(),q=read();
for(i=1;i<=n;++i)a[i]=read();
for(i=1;i<=m;++i)b[i]=read();
for(i=1;i<=n;++i)build(i,1,1,m);
while(q--){
LL l1=read(),r1=read(),l2=read(),r2=read(),mx=LLONG_MIN;
for(i=l1;i<=r1;++i){
LL mn=query(i,1,l2,r2);
if(mx<mn)mx=mn;
}
write(mx),putchar('\n');
}
}
算法2
(st表) O(nlogn)O(nlogn)
此题从博弈论上来讲并不算难题,因为每组最多取两次。
先考虑小Q,若小L取的数x>=0x>=0,则小Q必然取B[l2 r2]B[l2 r2]中的最小值,若小L取的数x<0x<0,则小Q必然取B[l2 r2]B[l2 r2]中的最大值。

接着考虑小L:
1.x>=0x>=0
则小Q必然取最小,设最小值为mn。
若mn>=0,则小L必然取>=0的最大值(可能不存在),否则小L取>=0的最小值。
2.x<0x<0
则小Q必然取最大,设最小值为mx。
若mx>=0,则小L必然取<0的最大值(可能不存在),否则小L取<0的最小值。

如何维护mn、mx、>=0的最大值,>=0的最小值,<0的最大值,<0的最小值mn、mx、>=0的最大值,>=0的最小值,<0的最大值,<0的最小值?
可以用6个ST表,对于不存在的情况记为-INF或INF即可,代码也不难实现,读者请自行完成

时间复杂度
ST表时间复杂度为O(nlogn)O(nlogn),总时间复杂度为O(nlogn+mlogm+qlogn)O(nlogn+mlogm+qlogn),约为O(nlogn)O(nlogn)

C++ 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF=1e9+1;
LL n,m,q;
LL a[100010],b[100010];
LL fb1[100010][18],fb2[100010][18],fa11[100010][18],fa12[100010][18],fa21[100010][18],fa22[100010][18];
//fb1:b中的max,fb2:b中的min,fa11:a中>=0的max,fa12:a中>=0的min,fa21:a中<0的max,fa22:a中<0的min
LL query(LL l,LL r,LL t)
{
LL k=log2(r-l+1);
if(t==1)return max(fb1[l][k],fb1[r-(1<<k)+1][k]);
else if(t==2)return min(fb2[l][k],fb2[r-(1<<k)+1][k]);
else if(t==3)return max(fa11[l][k],fa11[r-(1<<k)+1][k]);
else if(t==4)return min(fa12[l][k],fa12[r-(1<<k)+1][k]);
else if(t==5)return max(fa21[l][k],fa21[r-(1<<k)+1][k]);
else return min(fa22[l][k],fa22[r-(1<<k)+1][k]);
}
int main()
{
LL i,j;
cin>>n>>m>>q;
for(i=1;i<=n;i++)cin>>a[i];
for(i=1;i<=m;i++)cin>>b[i];
for(j=0;j<=16;j++)
for(i=1;i+(1<<j)-1<=m;i++)
if(!j)fb1[i][j]=fb2[i][j]=b[i];
else{
fb1[i][j]=max(fb1[i][j-1],fb1[i+(1<<j-1)][j-1]);
fb2[i][j]=min(fb2[i][j-1],fb2[i+(1<<j-1)][j-1]);
}

for(j=0;j<=16;j++)
for(i=1;i+(1<<j)-1<=n;i++)
if(!j){
if(a[i]>=0){
fa21[i][j]=-INF;
fa22[i][j]=INF;
fa11[i][j]=fa12[i][j]=a[i];
}
else{
fa11[i][j]=-INF;
fa12[i][j]=INF;
fa21[i][j]=fa22[i][j]=a[i];
}
}
else{
fa11[i][j]=max(fa11[i][j-1],fa11[i+(1<<j-1)][j-1]);
fa12[i][j]=min(fa12[i][j-1],fa12[i+(1<<j-1)][j-1]);
fa21[i][j]=max(fa21[i][j-1],fa21[i+(1<<j-1)][j-1]);
fa22[i][j]=min(fa22[i][j-1],fa22[i+(1<<j-1)][j-1]);
}

while(q--){
LL l1,r1,l2,r2;
cin>>l1>>r1>>l2>>r2;
LL mxb=query(l2,r2,1),mnb=query(l2,r2,2),ans=LLONG_MIN;
if(query(l1,r1,3)>=0)ans=max(ans,query(l1,r1,3)*mnb);
if(query(l1,r1,4)<INF)ans=max(ans,query(l1,r1,4)*mnb);
if(query(l1,r1,5)>-INF)ans=max(ans,query(l1,r1,5)*mxb);
if(query(l1,r1,6)<0)ans=max(ans,query(l1,r1,6)*mxb);
cout<<ans<<endl;
}
}

标签:r1,r2,题解,LL,T2,S2022,l1,l2,query
From: https://www.cnblogs.com/Limie/p/16885882.html

相关文章

  • Codeforces Round #833 (Div. 2) A-C题解
    比赛链接A、手摸不难发现,能做出的正方形大小就是当前的最大长度。所以直接输出向上取整即可。点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineN......
  • CSP-J2022题解
    CSP-J2022题解T1乘方思路非常简单,直接for循环上就行了。为什么不会炸呢?因为就算a=1e9,乘两次也炸不了longlong。代码#include<cstdio>longlonga,n,ans=1;intmai......
  • 2022/11/12 模拟测题解
    2022/11/12模拟测题解A考场上推了一下,发现这个玩意挺有意思。一共有\((n+1)(m+1)\)个字符串,减去相同的个数,即可。这个相同的个数还是很好统计的,且这里指的相同仅仅是......
  • ACM-ICPC World Finals 2022 L Where Am I? 题解
    题目链接我们要干的事情其实是对于输入矩阵中的每个位置,求出从它开始至少走几步形成的序列能跟所有位置走同样步数形成的序列不同。注意到每个位置至少走\(200^2\)步就能......
  • ACM-ICPC World Finals 2022 L Where Am I? 题解
    题目链接我们要干的事情其实是对于输入矩阵中的每个位置,求出从它开始至少走几步形成的序列能跟所有位置走同样步数形成的序列不同。注意到每个位置至少走\(200^2\)步就能......
  • 题解 AGC036D【Negative Cycle】
    problem(fromluogu)有一个\(N\)个点的有向图,节点标号为\(0\sim(N-1)\)。这张图初始时只有\(N-1\)条边,每条边从\(i\)指向\(i+1\),边权为\(0\)。对于每一......
  • 题解 CF1051F【The Shortest Statement】
    problem连通图,无自环,无重边,\(m-n\leq20\),\(n\leq10^5\),\(10^5\)询问两点之间最短路。solution搞出任意一棵生成树。一共\(21\)条非树边。对于任意一条路径,它只有......
  • ABC277E 题解
    前言题目传送门!更好的阅读体验?非常套路的分层图,纪念赛时切掉了。思路我们以样例来解释。首先,这是最基础的图。我们把图分成两层:第一层是原本\(w=1\)的路可以通......
  • ABC277D 题解
    前言题目传送门!或许更好的阅读体验?比较简单的模拟。思路首先把\(a_i\)排序。每次往后一直跑,如果不能再取了,就停下。但是这样做是\(O(n^2)\)的。我们需要优化。......
  • EasyExcel低版本中数据行中包含空数据会跳过导致数据对应不上的问题解析
    文章摘自:https://blog.csdn.net/caijwjava/article/details/100855361实战1、导入一个相关依赖即可<dependency><groupId>com.alibaba</groupId><artifactId>easyexc......