Gravatar
jacken
积分:98
提交:23 / 34

这道题不止一种做法,我用的是其中一种:贪心+RMQ


## 贪心的思路:


### 1.小L如果有正有负,分为三种情况:


#### (1)小Q只有正,这种情况对小Q不利,小L选择最大的正数(这里包括0,下同),小Q被逼的死路一条,只有选择最小的正数可以尽量实得分更小。


#### (2)小Q只有负,这种情况也对小Q不利,由于负负得正,小L选择绝对值最大的负数(相当于最小的负数),小Q没办法,只好选择绝对值最小的负数(相当于最大的负数),可以尽量实得分更小。


#### (3)小Q有正有负,这种情况对小Q有利,为何?因为小L出正,小Q出负,小L出负,小Q出正,小L不管怎么出,小Q都有办法使得它<=0,小L只能在出正或出负的情况选一个最小的,小L的第一个选择(正数),应选最小的正数,小Q就选最小的负数。小L的第二个选择(负数),应选最大的负数,小Q选最大的正数。


### 2.小L只有负,分为两种情况:


#### (1)小Q只有负,这种情况对小Q不利,由于负负得正,小L选择绝对值最大的负数(相当于最小的负数),小Q没办法,只好选择绝对值最小的负数(相当于最大的负数),可以尽量实得分更小。


#### (2)小Q只有正或有正有负,这种情况对小Q有利,小L没办法,选绝对值最小的负数(相当于最大的负数),小Q选择最大的正数。


### 3.小L只有正,分为两种情况:


#### (1)小Q只有正,这种情况对小Q不利,小L选择最大的正数,小Q选最小的正数。


#### (2)小Q只有负或有正有负,这种情况对小Q有利,小L没办法,只好选择最小的的正数,小Q选择绝对值最大的负数(相当于最小的负数)。


## 代码部分:


### 准备八个数组:fza,fza1,fzb,fzb1,ffa,ffa1,ffb,ffb1,分别代表小L正数最大值、小L正数最小值、小Q正数最大值、小Q正数最小值、小L负数最大值、小L负数最小值、小Q负数最大值、小Q负数最小值。


### 初始化:属于这个部分的(负数或正数)就直接赋值,否则是大的就-1e10,小的就1e10。


### 剩下的就按思路做。


### 代码:


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5;
int a[N];
int b[N];
int fza[N][20];
int fza1[N][20];
int fzb[N][20];
int fzb1[N][20];
int ffa[N][20];
int ffa1[N][20];
int ffb[N][20];
int ffb1[N][20];
int n,q,m;
signed main()
{
    scanf("%lld %lld %lld",&n,&m,&q);
    for(int i = 1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        fza[i][0] = a[i]>=0?a[i]:(int)-1e10;
        fza1[i][0] = a[i]>=0?a[i]:(int)1e10;
        ffa[i][0] = a[i]<0?a[i]:(int)-1e10;
        ffa1[i][0] = a[i]<0?a[i]:(int)1e10;
    }
    for(int i = 1;i<=m;i++)
    {
        scanf("%lld",&b[i]);
        fzb[i][0] = b[i]>=0?b[i]:(int)-1e10;
        fzb1[i][0] = b[i]>=0?b[i]:(int)1e10;
        ffb[i][0] = b[i]<0?b[i]:(int)-1e10;
        ffb1[i][0] = b[i]<0?b[i]:(int)1e10;
    }
    for(int i = 1;i<=log2(n);i++)
    {
        for(int j = 1;j<=n-(1<<i)+1;j++)
        {
            fza[j][i] = max(fza[j][i-1],fza[j+(1<<(i-1))][i-1]);
            fza1[j][i] = min(fza1[j][i-1],fza1[j+(1<<(i-1))][i-1]);
            ffa[j][i] = max(ffa[j][i-1],ffa[j+(1<<(i-1))][i-1]);
            ffa1[j][i] = min(ffa1[j][i-1],ffa1[j+(1<<(i-1))][i-1]);
        }
    }
    for(int i = 1;i<=log2(m);i++)
    {
        for(int j = 1;j<=m-(1<<i)+1;j++)
        {
            fzb[j][i] = max(fzb[j][i-1],fzb[j+(1<<(i-1))][i-1]);
            fzb1[j][i] = min(fzb1[j][i-1],fzb1[j+(1<<(i-1))][i-1]);
            ffb[j][i] = max(ffb[j][i-1],ffb[j+(1<<(i-1))][i-1]);
            ffb1[j][i] = min(ffb1[j][i-1],ffb1[j+(1<<(i-1))][i-1]);
        }
    }
    for(int i = 1;i<=q;i++)
    {
        int la,ra,lb,rb;
        scanf("%lld %lld %lld %lld",&la,&ra,&lb,&rb);
        int kl = log2(ra-la+1);
        int num;
        int kr = log2(rb-lb+1);
        if(max(fza[la][kl],fza[ra-(1<<kl)+1][kl])!=(int)-1e10&&max(ffa[la][kl],ffa[ra-(1<<kl)+1][kl])!=(int)-1e10)
        {
            if(max(ffb[lb][kr],ffb[rb-(1<<kr)+1][kr]) == (int)-1e10)
            {
                num = max(fza[la][kl],fza[ra-(1<<kl)+1][kl])*min(fzb1[lb][kr],fzb1[rb-(1<<kr)+1][kr]);
            }
            if(max(fzb[lb][kr],fzb[rb-(1<<kr)+1][kr]) == (int)-1e10)
            {
                num = min(ffa1[la][kl],ffa1[ra-(1<<kl)+1][kl])*max(ffb[lb][kr],ffb[rb-(1<<kr)+1][kr]);
            }
            if(max(fzb[lb][kr],fzb[rb-(1<<kr)+1][kr])!=(int)-1e10&&max(ffb[lb][kr],ffb[rb-(1<<kr)+1][kr])!=(int)-1e10)
            {
                int L1 = min(fza1[la][kl],fza1[ra-(1<<kl)+1][kl])*min(ffb1[lb][kr],ffb1[rb-(1<<kr)+1][kr]),L2 = max(ffa[la][kl],ffa[ra-(1<<kl)+1][kl])*max(fzb[lb][kr],fzb[rb-(1<<kr)+1][kr]);
                num = max(L1,L2);
            }
        }
        if(max(fza[la][kl],fza[ra-(1<<kl)+1][kl]) == (int)-1e10&&max(ffa[la][kl],ffa[ra-(1<<kl)+1][kl])!=(int)-1e10)
        {
            if(max(fzb[lb][kr],fzb[rb-(1<<kr)+1][kr]) == (int)-1e10&&max(ffb[lb][kr],ffb[rb-(1<<kr)+1][kr])!=(int)-1e10)
            {
                num = min(ffa1[la][kl],ffa1[ra-(1<<kl)+1][kl])*max(ffb[lb][kr],ffb[rb-(1<<kr)+1][kr]);
            }
            else
            {
                num = max(ffa[la][kl],ffa[ra-(1<<kl)+1][kl])*max(fzb[lb][kr],fzb[rb-(1<<kr)+1][kr]);
            }
        }
        if(max(fza[la][kl],fza[ra-(1<<kl)+1][kl])!=(int)-1e10&&max(ffa[la][kl],ffa[ra-(1<<kl)+1][kl]) == (int)-1e10)
        {
            if(max(fzb[lb][kr],fzb[rb-(1<<kr)+1][kr])!=(int)-1e10&&max(ffb[lb][kr],ffb[rb-(1<<kr)+1][kr]) == (int)-1e10)
            {
                num = max(fza[la][kl],fza[ra-(1<<kl)+1][kl])*min(fzb1[lb][kr],fzb1[rb-(1<<kr)+1][kr]);
            }
            else
            {
                num = min(fza1[la][kl],fza1[ra-(1<<kl)+1][kl])*min(ffb1[lb][kr],ffb1[rb-(1<<kr)+1][kr]);
            }
        }
        printf("%lld\n",num);
    }
    return 0;
}

题目3782  [CSP 2022S]策略游戏 AAAAAAAAAAAAAAAAAAAA      6      评论
2024-01-06 19:03:41    
Gravatar
jacken
积分:98
提交:23 / 34

可以用RMQ

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
int a[N];
int f[N][20];
int n,k;
int main()
{
    scanf("%d %d",&n,&k);
    for(int i = 1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        f[i][0] = a[i];
    }
    for(int i = 1;i<=log2(n);i++)
    {
        for(int j = 1;j<=n-(1<<i)+1;j++)
        {
            f[j][i] = min(f[j][i-1],f[j+(1<<(i-1))][i-1]);
        }
    }
    for(int i = 1;i+k-1<=n;i++)
    {
        int x = i,y = i+k-1;
        int k = log2(y-x+1);
        printf("%d ",min(f[x][k],f[y-(1<<k)+1][k]));
    }
    printf("\n");
    for(int i = 1;i<=n;i++)
    {
        f[i][0] = a[i];
    }
    for(int i = 1;i<=log2(n);i++)
    {
        for(int j = 1;j<=n-(1<<i)+1;j++)
        {
            f[j][i] = max(f[j][i-1],f[j+(1<<(i-1))][i-1]);
        }
    }
    for(int i = 1;i+k-1<=n;i++)
    {
        int x = i,y = i+k-1;
        int k = log2(y-x+1);
        printf("%d ",max(f[x][k],f[y-(1<<k)+1][k]));
    }
    return 0;
}


题目495  [POJ 2823]滑动窗口 AAAAAAAAA      2      评论
2024-01-06 18:47:43    
Gravatar
noi加油
积分:49
提交:46 / 181
×

提示!

该题解未通过审核,建议分享者本着启发他人,照亮自己的初衷以图文并茂形式完善之,请勿粘贴代码。

#include<bits/stdc++.h>

using namespace std;

int main()



........................................................................

该题解等待再次审核

........................................................................(剩余 490 个中英字符)

题目3049  [NOIP 2018PJ]标题统计
2024-01-04 20:08:13    
Gravatar
op_组撒头屯
积分:2982
提交:327 / 662

“引爆逆天力量,追寻圆环之理的神藏奥秘”系列再现高手。

首先最终的树的点数可以达到 $10^{10}$ 级别,我们肯定不能真正把树建出来。

但是注意到我们可以只保留每个复制出的子树的根(记作关键点),那么这些根也构成一棵树,这样就好办了。

当询问 $dis(x,y)$ 时,我们先找到 $x$ 和 $y$ 分别从属于的关键点,并求出它们在关键点树上的距离,而这是容易预处理的。需要注意的是,在 lca 处涉及同一关键点范围内的距离,在原树上查其距离即可。

以及,在定位点时,涉及查询原树某棵子树内编号第 $k$ 大的点,把树拍成 dfn 序后主席树上二分即可。

时间复杂度 $O(n\log n)$,有点难写。


题目2052  [HNOI 2016] 树      5      2 条 评论
2023-12-21 22:09:47    
Gravatar
小刘同学
积分:105
提交:74 / 231

这道题主要考验枚举与拆位,可以按题目要求直接将三位数拆位就三次幂和判断相等与否(真水)

/除号

%取模号

百位:

    x/100

十位:

    x/10%10

个位

    x%10




题目368  水仙花数 AAAAA      3      评论
2023-12-03 08:34:54    
Gravatar
┭┮﹏┭┮
积分:2922
提交:742 / 1645

挺好的递推+恶心的矩阵快速幂题

题面:有一个n行m列的棋盘,在当前位置可以瞬移,每次可向右瞬移奇数列,且瞬移到本行或相邻行,并且不能瞬移出棋盘,问从$(1,1)至(n,m)$的总方案数

首先考虑递推,设$f(i,j)$为投当前在第i行第j列的方案数,因为每次可以向右瞬移,所以$f(i,j)$可以由上一列,上上上一列...推出来,且可以由上一行和下一行推出

则递推转移方程式为$f(i,j) = \sum_{k=j-w,w=1,w+=2}^j f(i,k)+f(i-1,k)+f(i+1,k)$

这样直接枚举是$O(nm^2)$的复杂度,肯定是不行的,那我们继续考虑

我们设$g(i,j) = \sum_{k=j-w,w=1,w+=2}^j f(i,k) = g(i,j-2) + f(i,j-1)$

则方程式转为$f(i,j) = g(i-1,j) + g(i,j) + g(i+1,j) = g(i-1,j-2) + f(i-1,j-1) + g(i,j-2) + f(i,j-1) + g(i+1,j-2) + f(i+1,j-1)$

我们在维护$f$的同时维护$g$则时间复杂度会降到$O(nm)$

一看数据$10^9$,再次拿出我们的dz,一眼鉴定为矩阵快速幂

然后就开始我们快(恶)乐(心)的推转移矩阵的时候:

根据转移方程我们可以分成两种情况,即上一列的方案和上上一列的方案,因为上上一列的方案数在推下一列的方案数时要用到,所以不能去掉,我们都需要记录,所以需要当推到$f(i,j)$时,我们需要$f(i,j-1), g(i,j-1), g(i,j-2)$把这三列归为一列,$1至n$为$f(i,j-1)$,$n+1至2n$为$g(i,j-1)$,$2n+1至3n$为$g(i,j-2)$最后该矩阵的长度为$3n$最大为150,则我们转移矩阵大小为$3n * 3n$

先看应该怎样转移

$$\begin{bmatrix}f(1,j-1) & f(2,j-1) & ... & f(n,j-1) & g(1,j-1) & g(2,j-1) & ... & g(n,j-1) & g(1,j-2) & g(2,j-2) & ... & g(n,j-2) \\\end{bmatrix}$$

应该转移为

$$\begin{bmatrix}f(1,j) & f(2,j) & ... & f(n,j) & g(1,j) & g(2,j) & ... & g(n,j) & g(1,j-1) & g(2,j-1) & ... & g(n,j-1) \\\end{bmatrix}$$

所以根据递推转移方程考虑转移矩阵,则可推出矩阵为:

设转移矩阵为$c(i,j)$

首先先看f的矩阵:根据递推方程 当$f(i,j)$时 只需将$c(i-1,i),c(i,i),c(i+1,i)$设为1,才加上$g$即将$c(2*n+i-1,i),c(2*n+i,i),c(2*n+i+1,i)$再设为1就可以了

再考虑$g(i,j)$ 由递推方程式得 应当将$c(i,i+n),c(i+2*n,i+n)$置为1即可

最后看$g(i,j-1)$ 在转移前已经出现,不需要推,所以只要将$c(i+n,i+2*n)$置为1即可

(因为矩阵实在太大画不下,只好描述一下)

Oo最后开始愉悦的矩阵快速幂时刻oO

复杂度为$O(150^3*log(1e9))$,大约为$1e8$所以跑的飞慢qwq

二维递推实在痛苦┭┮﹏┭┮










题目2976  偷笔记 AAAAAAAAAA      7      评论
2023-11-21 20:41:53