首页 > 其他分享 >【题解】Luogu[P8818] CSP-S 2022 策略游戏

【题解】Luogu[P8818] CSP-S 2022 策略游戏

时间:2023-05-13 22:34:01浏览次数:40  
标签:2022 选非 题解 P8818 负数 尽可能 res query 正数

一道简单区间rmq分类讨论题,考场上最后5分钟想出来,没写出来,退役了……

给定两个序列 \(A_{1},\dots,A_{n}\);\(B_1,\dots,B_n\) 规定 \(C_{i,j}=A_i\times B_i\)。
题目说小 L 和小 Q 必定选择最优策略,而小 L 先选,小 Q 后选,小 L 要使得 \(C_{i,j}\) 尽可能大,小 Q 要使得 \(C_{i,j}\) 尽可能小。
共 \(q\) 个询问。

考虑暴力

预处理出 \(C_{i,j}\),对于每个询问,枚举 $ C_{l_1,r_1} \sim C_{l_2,r_2} $ ,根据最优策略,小 L 会先找出一行,使得这一行中的最小值最大,使小 Q 所选出的值尽量不优。答案即为这一行中的最小值。

时间 \(O(qnm)\)
空间 \(O(nm)\)

考虑优化

仍然预处理出 \(C_{i,j}\)。
根据暴力,我们发现对于小 L 要找的那一行,我们需要每一行的区间最小值,于是不难想到,先预处理出每一行的最小值,然后对于每一个询问,枚举 \(l_1 \sim l_2\) 对于每一行,查询区间 $ r_1 \sim r_2 $ 的最小值,找到一行使得最小值最大,答案即为这一行中的最小值。

时间 \(O(qn)\)
空间 \(O(nm)\)

考虑再次优化

对于暴力空间 \(O(nm)\) 我们知道一定无法通过本题,故我们需要不通过预处理 \(C\) 来进行求解。

观察特殊性质我们发现有特殊性质 1 保证 \(A_i,B_i>0\) 即保证其为正整数,对 \(A_i,B_i\) 的正负号进行了规定,这也提示了我们,观察题目所给的 \(C_{i,j} = A_i \times B_j\),对于乘法我们知道,正正得正,负负得负,正负得负,零乘任意数得零。于是我们可以对 \(A_i,B_i\) 的正负号进行讨论。

对于当小 L 所选区域 \(A_{l_1}\sim A_{l_2}\) 中:

  1. \(A_i\) 均为非负数
  2. \(A_i\) 均为非正数
  3. \(A_i\) 有正有负有零

则小 Q 所选区域 \(B_{r_1}\sim B_{r_2}\) 同时也有:

  1. \(B_i\) 均为非负数
  2. \(B_i\) 均为非正数
  3. \(B_i\) 有正有负有零

我们进行分类讨论。

对于小 Q 第一种情况,无论小 L 所选数的正负,都要让该数尽可能大,这样 \(A_i \times B_i\) 才能尽可能大,使得自己分数尽可能大;而当小 L 选非负数时,小 Q 则需要选最小的非负数使得乘积尽可能小,自己得分尽可能大;而当小 L 选非正数时,小 Q 则需要选最大的非负数使得乘积尽可能小。则小 L 需要考虑对于小 Q 的两种选取情况哪一种能使值最大,自己的得分尽可能大,故值即为两种情况的最大值。

对于小 Q 第二种情况,无论小 L 所选数的正负,都要让该数尽可能小,这样 \(A_i \times B_i\) 才能尽可能大,使得自己分数尽可能大;而当小 L 选非负数时,小 Q 则需要选最小的非正数使得乘积尽可能小,自己得分尽可能大;而当小 L 选非正数时,小 Q 则需要选最大的非负数使得乘积尽可能小。则小 L 需要考虑对于小 Q 的两种选取情况哪一种能使值最大,自己的得分尽可能大,故值即为两种情况的最大值。

对于小 Q 第三种情况,
若小 L 可选非正数,则小 Q 必选最大的非负数使得乘积为负且最小,故小 L 需要让该非正数尽可能大,使得乘积尽可能大,自己得分尽可能大。所以小 L 选非正数最大,小 Q 选非负数最大;
若小 L 可选非负数,则小 Q 必选最小的非正数使得乘积为负且最小,故小 L 需要让该非负数尽可能小,使得乘积尽可能大,自己得分尽可能大,所以小 L 选非负数最小,小 Q 选非正数最小。
故小 L 需要比较小 Q 的两种选取方式哪个值更大,最终答案即为两值中更大的。

这样,我们就无需预处理 \(C\),仅对每次询问的 \(A,B\) 进行分来讨论即可求得答案。

对于我们要查询的 \(A\) 中非正数最大、最小,非负数最大、最小;\(B\) 中非正数最大、最小,非负数最大、最小,可以用 st 表或线段树轻松预处理出来。

我选择 st 表,用 \(O(n \log n)\) 预处理,对于每个询问都 \(O(1)\) 查询。
时间 \(O(n\log n+q)\)

本题于是就做完了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int NR=1e5+5;
const int KR=50;
const int MX=1e9+5;
const int MN=-1e9-5;
#define rep(x) for(int i=1;i<=x;++i)
#define repi(x) for(int i=1;i+(1<<k)-1<=x;++i)
#define repk(x) for(int k=1;(1<<k)<=x;++k)
int n,m,q;
int a[NR],b[NR];
//g开头即维护的是非正数,f开头即维护的是非负数
//x结尾即维护最大值,n结尾即维护最小值
int fax[NR][KR],fan[NR][KR],gax[NR][KR],gan[NR][KR];//序列a的
int fbx[NR][KR],fbn[NR][KR],gbx[NR][KR],gbn[NR][KR];//序列b的
struct Q{
    int fax,fan,gax,gan;
    int fbx,fbn,gbx,gbn;
};
void init(){//维护st表
    rep(n)
        repk(n)
            fax[i][k]=gax[i][k]=MN,fan[i][k]=gan[i][k]=MX;
    rep(m)
        repk(m)
            fbx[i][k]=gbx[i][k]=MN,fbn[i][k]=gbn[i][k]=MX;
    repk(n)
        repi(n)
            fax[i][k]=max(fax[i][k-1],fax[i+(1<<k-1)][k-1]),
            gax[i][k]=max(gax[i][k-1],gax[i+(1<<k-1)][k-1]),
            fan[i][k]=min(fan[i][k-1],fan[i+(1<<k-1)][k-1]),
            gan[i][k]=min(gan[i][k-1],gan[i+(1<<k-1)][k-1]);
    repk(m)
        repi(m)
            fbx[i][k]=max(fbx[i][k-1],fbx[i+(1<<k-1)][k-1]),
            gbx[i][k]=max(gbx[i][k-1],gbx[i+(1<<k-1)][k-1]),
            fbn[i][k]=min(fbn[i][k-1],fbn[i+(1<<k-1)][k-1]),
            gbn[i][k]=min(gbn[i][k-1],gbn[i+(1<<k-1)][k-1]);
}
int query(int F[NR][KR],int L,int R,int B){
    int K=log2(R-L+1);
    if(B==1)return max(F[L][K],F[R-(1<<K)+1][K]);
    return min(F[L][K],F[R-(1<<K)+1][K]);
}
signed main(){
    cin>>n>>m>>q;
    for(int i=1;i<=n;++i){
        cin>>a[i];
        fax[i][0]=gax[i][0]=MN;
        fan[i][0]=gan[i][0]=MX;
        if(a[i]>=0)fax[i][0]=fan[i][0]=a[i];
        if(a[i]<=0)gax[i][0]=gan[i][0]=a[i];
    }
    for(int i=1;i<=m;++i){
        cin>>b[i];
        fbx[i][0]=gbx[i][0]=MN;
        fbn[i][0]=gbn[i][0]=MX;
        if(b[i]>=0)fbx[i][0]=fbn[i][0]=b[i];
        if(b[i]<=0)gbx[i][0]=gbn[i][0]=b[i];
    }
    init();
    while(q--){
        int lL,lR,qL,qR,ans=-1e18-5;
        cin>>lL>>lR>>qL>>qR;
        Q res;
        res.fax=query(fax,lL,lR,1),res.fan=query(fan,lL,lR,-1);
        res.gax=query(gax,lL,lR,1),res.gan=query(gan,lL,lR,-1);
        res.fbx=query(fbx,qL,qR,1),res.fbn=query(fbn,qL,qR,-1);
        res.gbx=query(gbx,qL,qR,1),res.gbn=query(gbn,qL,qR,-1);
        if(res.fbn!=MX&&res.gbx!=MN){//小 Q 有非正有非负
            if(res.gax!=MN)//小 L 可以选非正数
                ans=max(ans,res.gax*res.fbx);
            if(res.fan!=MX)//小 L 可以选非负数
                ans=max(ans,res.fan*res.gbn);
            // cout<<"-1-"<<endl;
        }
        else if(res.gbx!=MN&&res.fbx==MN){//小 Q 只有非正
            if(res.gan!=MX)//小 L 可以选非正数
                ans=max(ans,res.gan*res.gbx);
            if(res.fan!=MX)//小 L 可以选非负数
                ans=max(ans,res.fan*res.gbn);
            // cout<<"-2-"<<endl;
        }
        else if(res.fbn!=MX&&res.gbn==MX){//小 Q 只有非负
            if(res.fax!=MN)//小 L 可以选非负数
                ans=max(ans,res.fax*res.fbn);
            if(res.gax!=MN)//小 L 可以选非正数
                ans=max(ans,res.gax*res.fbx);
            // cout<<"-3-"<<endl;
        }
        std::cout<<ans<<endl;
    }
    return 0;
}

以此,纪念初中最后一次 CSP。以此,纪念我那美好的信竞生涯。

标签:2022,选非,题解,P8818,负数,尽可能,res,query,正数
From: https://www.cnblogs.com/agrumestly/p/17398380.html

相关文章

  • 【题解】Luogu[P1879] [USACO06NOV]Corn Fields G
    Link→状压dp典题,看数据范围就能多半猜到是状压。\(M\)行\(N\)列很不舒服,本篇题解规定为\(N\)行\(M\)列。因为说没有哪两块草地相连,我们不妨一行一行考虑,一行中每格只可能是\(0\)或\(1\),所以一行的总不同状态数是\(2^M\)。我们用二进制表示每一行的状态,对于每一行,暴......
  • 【笔记】学习笔记2022-12-31
    title:'学习笔记2022-12-31'date:2022-12-3114:00:03tags:-'离散化'-分块-数论分块-操作分块-根号分治categories:-笔记-学习笔记2022-12-31离散化把值域很大的一组数映射到值域较小的一组数,相对关系不变P3740[HAOI2014]贴海报:记录线段......
  • 【题解】Luogu[P1967] NOIP2013 提高组 货车运输
    Link→很容易想到一个暴力做法,就是跑一遍Floyd,\(F_{i,j}\)表示\(i\)到\(j\)最大载重量,转移\(F_{i,j}=\max\{F_{i,j},\min\{F_{i,k},F_{k,j}\}\}\)。显然时间复杂度\(O(n^3)\)是过不了的。我们发现,因为是求两点路径中使得最小值最大,实际上有一些较小的路径是不会走......
  • IDEA 破解激活2022.2
    IDEA破解激活可以激活2022.3、2022.1或2022.2过程下载jetbra.zip激活工具包,解压(目录无中文、无空格),Windows直接双击install-all-users.vbs或者install-current-user.vbs脚本说明:因为脚本会修改环境变量,所以在Windows系统可能会被安全软件拦截,大家允许执行即......
  • CF1698F题解
    考虑一个函数\(f(a)\),它的返回值是一个二维数组\(b\),接受值是一个数组\(a\)。对于所有\(i=1\ton-1\)的\(i\),把\(b_{a_i}{a_{i+1}}++\),然后返回\(b\)。\(f(a)!=f(b)\)且\(a_1=b_1,a_n=b_n\)是无解的充要条件,因为显然对于数组的每次翻转操作它的\(f\)返回值都不会变。\(f(a)!=f(b......
  • P8496 [NOI2022] 众数
    补题狗不发表评论,但是摩尔投票是不是有点那啥小心deque摩尔投票对于一个数列,如果其众数出现次数严格大于数列长度的一半,就可以用摩尔投票的方式\(O(n)\)求出众数。当众数出现次数小于一半时,求出众数之后还需要检验。模板:P2397yyylovesMathsVI(mode)摩尔投票具有可加......
  • CF1777D Score of a Tree 题解
    题目简述给你一个\(n\)个结点根为\(1\)的树。在\(t=0\)时,每个结点都有一个值,为\(0\)或\(1\)。在每一个\(t>0\)时,每个结点的值都会变成其子结点在\(t-1\)时的值的异或和。定义\(S(t)\)为\(t\)时所有结点值的和。定义\(F(A)\)为树在\(0\let\le10^......
  • vs2022+qt 通过qss文件给QPushButton控件设置样式
    新建QSS文件1)在Qt项目文件夹中,“右键”---“新建”---“文本文档”,并将其改成.qss后缀在里面写入样式信息:/*正常状态或者鼠标松开按钮的状态,按钮颜色*/QPushButton{background-color:rgb(240,255,255);color:rgb(0,0,2);border-style:outset;bo......
  • CF1777C Quiz Master题解
    题目简述给定一个长度为\(n\)的正整数序列\(a\),以及一个正整数\(m\)。在序列\(a\)中选出一个长度为子序列(不是子段)\(b\),\(\foralli\in[1,m],\existsb_j,b_j\)能整除\(i\)。求所有满足条件的序列\(b\)的极差(最大值于最小值的差)的最小值;若无满足条件序列\(b\)......
  • MATLAB2022安装教程
    MATLAB2022破解版下载一.下载连接https://pan.baidu.com/s/17OToNAw0w9Vvt-V278nCHw?pwd=kc8f二.解压Crack.rar文件三.安装步骤双击R2022b_Windows.iso加载文件,然后点击里面的setup.exe文件打开后点击右上角高级选项->我有文件安装秘钥->我同意,下一步输入秘钥.txt中的数......