P4392 [BOI2007]静音问题 题解

传送门:P3942

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

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

考虑到每个序列的长度是固定的,我们可以先进行一次ST表操作,记录下vali= max{ai →ai+m} 。再在同一个f数组中进行第二次ST表操作,计算出fi = min{ai → 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;
}

 

原文地址:https://www.cnblogs.com/begin-AC/p/11385694.html

时间: 2024-10-11 08:18:23

P4392 [BOI2007]静音问题 题解的相关文章

Luogu P4392 [BOI2007]Sound 静音问题

Luogu P4392 [BOI2007]Sound 静音问题 解析 挺简单的一道线段树题目,区间长度已经给定,只需用线段树处理区间最大.最小值,然后枚举区间左端点,判断这段区间是否合法即可 Code #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define LL long long using namespa

题解 P4393 【[BOI2007]Sequence 序列问题】

Solution: 对于每个很大的数,基于贪心,我们显然要让它合并次数尽可能少,以保证最终总代价最小. 如图: 考虑中间那个最大的 $maxn$,很显然,将其与其它的合并代价显然更大,所以,我们不可能先用 $maxn$ 去和其它的合并. 但是,由于最终目标长度为1,所以无论如何,$maxn$ 终将被合并,可以先考虑将比它小的全部合并,最后再与它合并,以减少它参与合并的次数. 不难想到,可以先将 $maxn$ 左边全部合并,再将其右边全部合并,最后,再让左右两部分与它合并,这样可以保证比先合并 $

1342: [Baltic2007]Sound静音问题

1342: [Baltic2007]Sound静音问题 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 710  Solved: 307[Submit][Status][Discuss] Description 静音问题 数字录音中,声音是用表示空气压力的数字序列描述的,序列中的每个值称为一个采样,每个采样之间间隔一定的时间. 很多声音处理任务都需要将录到的声音分成由静音隔开的几段非静音段.为了避免分成过多或者过少的非静音段,静音通常是这样定义的:m

洛谷 P1079 Vigen&#232;re 密码 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1079 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为 南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用 M 表示:称加密后的信息为密文,用 C 表示:而密钥是一种

8.8联考题解

今天的T1让我怀疑我是不是在做奥赛题--这考的是什么知识点啊这个,会不会用绝对值函数? Evensgn 的债务 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Evensgn 有一群好朋友,他们经常互相借钱.假如说有三个好朋友A,B,C.A 欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元.Evensgn 是个追求简约的人,他觉得这样的债务太繁杂了.他认为,上面的债务可以完全等价为 A 欠C20 元,B 既不欠别人,别人也不欠他.这样总债务规模就压缩到了 

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

(leetcode题解)Pascal&#39;s Triangle

Pascal's Triangle  Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] 题意实现一个杨辉三角. 这道题只要注意了边界条件应该很好实现出来,C++实现如下 vector<vector<int>> generate(int

2017ZZUACM省赛选拔试题部分题解----谨以纪念我这卡线滚粗的美好经历

写在前面: 其实心里有些小小的不爽又有点小小的舒畅,为啥捏?不爽当然是因为没被选拔上啦,舒畅捏则是因为没被选拔上反而让自己警醒,学长也提点很多很多."沉下去,然后一战成名"学长如是对我说,我很开心.其实这完全算不算是题解,只是我个人的一些小想法而已.而且到现在还有一题不会...让自己长点记性吧. 题目 A :聪明的田鼠 Time Limit: 1 Sec Memory Limit: 128 MB Description 田鼠MIUMIU来到了一片农田,农田可以看成是一个M*N个方格的矩

LeetCode-001题解

此题目摘自LeetCode001 Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.