简要题意
有两串数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;
}
}