P4392 [BOI2007]静音问题 题解

Posted begin-ac

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4392 [BOI2007]静音问题 题解相关的知识,希望对你有一定的参考价值。

传送门:P3942

这道题要求我们对所有长度为m的序列,找出其中最大值和最小值的差值不超过c的,并输出它们的起始位置。

看到静态序列最值问题,很自然的想到要用ST表进行Θ(nlogn+n)预处理、Θ(1)查询。但是很不幸,如果直接用两个表分别存储最大值和最小值,最后一个点妥妥的MLE,因此我们需要对空间占用进行优化。

考虑到每个序列的长度是固定的,我们可以先进行一次ST表操作,记录下vali= maxai →ai+m 。再在同一个f数组中进行第二次ST表操作,计算出fi = minai → ai+m,最后1→(n - m)扫描一次各元素,满足条件vali - fi ≤ c时输出i即可。同时,由于序列长度固定为m,所以我们不需要像一般的ST表一样开一个O(nlogn)的数组,开一个O(nlogm)的数组即可存储下全部有效信息,因此第二维可以缩小至 log2m  = 15。经过这两次优化,程序的空间复杂度降低至可以接受的程度,可以开心的A掉这道题。完整代码如下:

#include <iostream>
#include <cstdio>
using namespace std;
int n;
int val[1000010], f[1000005][15];

inline int max(int x, int y)
    return x > y ? x : y;


inline int min(int x, int y)
    return x < y ? x : y;


inline void init1() 
    for (int i = 1; i <= n; i++) scanf("%d", &f[i][0]);//直接输入,节约空间
    for (int j = 1; j <= 14; j++)
        for(int i = 1; i + (1 << j) - 1 <= n; i++)
            f[i][j] = max(f[i][j - 1], f[ i + (1 << (j - 1) ) ][j - 1]);//预处理区间最大值

inline void init2() 
    for (int j = 1; j <= 14; j++)
        for (int i = 1; i + (1 << j) - 1 <= n; i++)
            f[i][j] = min(f[i][j - 1], f[ i + (1 << (j - 1) ) ][j - 1]);//预处理区间最小值


int k;
int find1(int l, int r) 
    return max(f[l][k], f[r - (1 << k) + 1][k]);//查询区间最大值

int find2(int l, int r) 
    return min(f[l][k], f[r - (1 << k) + 1][k]);//查询区间最小值


int main() 
    int m, c;
    scanf("%d%d%d", &n, &m, &c);//按题意输入
    init1();//预处理最大值
    while( (1 << (k + 1) ) <= m) k++;//计算出区间长度
    for (int i = 1, j = i + m - 1; j <= n; i++, j++)
        val[i] = find1(i, j);
    //记录下区间最大值
    init2();//预处理区间最小值
    int ok = 0;//用于记录是否下是否有合法的序列
    for(int i = 1, j = i + m - 1; j <= n; i++, j++)
        if(val[i] - find2(i, j) <= c)
            ok = printf("%d\n", i);
//这里运用了printf函数在成功输出后会返回输出元素个数的性质,只要有输出,ok就会被赋上一个非0值
    
    if(!ok) puts("NONE");//特判没有合法区间的情况
    return 0;

 

 

以上是关于P4392 [BOI2007]静音问题 题解的主要内容,如果未能解决你的问题,请参考以下文章

题解 P4393 [BOI2007]Sequence 序列问题

BOI2007摩基亚Mokia

[BOI2007] Mokia

BZOJ 1342: [Baltic2007]Sound静音问题 | 单调队列维护的好题

[BOI2007]Mokia 摩基亚

「BOI2007」Mokia