Luogu P4392 [BOI2007]Sound 静音问题

Luogu P4392 [BOI2007]Sound 静音问题

解析

  • 挺简单的一道线段树题目,区间长度已经给定,只需用线段树处理区间最大、最小值,然后枚举区间左端点,判断这段区间是否合法即可

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int N=1e6+5;
int n,m,c,h[N];
bool flag;
struct Tree
{
    struct tree
    {
        int minn,maxx;
    }tr[N<<2];
    void pushup(int root)
    {
        tr[root].minn=min(tr[root*2].minn,tr[root*2+1].minn);
        tr[root].maxx=max(tr[root*2].maxx,tr[root*2+1].maxx);
        return;
    }
    void build(int root,int l,int r)
    {
        if(l==r)
        {
            tr[root].minn=tr[root].maxx=h[l];
            return;
        }
        int mid=(l+r)>>1;
        build(root*2,l,mid);
        build(root*2+1,mid+1,r);
        pushup(root);
        return;
    }
    int query(int root,int l,int r,int ll,int rr,int fag)
    {
        if(ll<=l&&r<=rr)
        {
            if(fag==1) return tr[root].minn;
            else return tr[root].maxx;
        }
        int mid=(l+r)>>1;
        if(mid>=rr) return query(root*2,l,mid,ll,rr,fag);
        else
        {
            if(mid<ll) return query(root*2+1,mid+1,r,ll,rr,fag);
            else
            {
                if(fag==1) return min(query(root*2,l,mid,ll,mid,fag),query(root*2+1,mid+1,r,mid+1,rr,fag));
                else return max(query(root*2,l,mid,ll,mid,fag),query(root*2+1,mid+1,r,mid+1,rr,fag));
            }
        }
    }
}str;
bool check(int x)
{
    int mins=str.query(1,1,n,x,x+m-1,1);
    int maxs=str.query(1,1,n,x,x+m-1,2);
    return (maxs-mins<=c)?1:0;
}
int main()
{
    scanf("%d%d%d",&n,&m,&c);
    for(int i=1;i<=n;i++) scanf("%d",&h[i]);
    str.build(1,1,n);
    for(int i=1;i<=n-m+1;i++)
    {
        if(check(i))
        {
            flag=1;
            printf("%d\n",i);
        }
    }
    if(!flag) puts("NONE");
    return 0;
}

原文地址:https://www.cnblogs.com/Hawking-llfz/p/11599627.html

时间: 2024-10-04 12:29:55

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

1342: [Baltic2007]Sound静音问题

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

[bzoj1342][Baltic2007]Sound静音问题_单调队列

Sound静音问题 bzoj-1342 Baltic-2007 题目大意:给定一个n个数的序列,求所有的长度为m的区间,使得区间内最大值减去最小值不超过阈值c. 注释:$1\le n \le 10^6$,$1\le m\le 10^4$. 想法:单调队列裸题. 定长区间最值问题显然可以用单调队列维护. 最后,附上丑陋的代码... ... #include <iostream> #include <cstdio> #include <cstring> #include &

Sound静音问题

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

P4392 [BOI2007]静音问题 题解

传送门:P3942 这道题要求我们对所有长度为m的序列,找出其中最大值和最小值的差值不超过c的,并输出它们的起始位置. 看到静态序列最值问题,很自然的想到要用ST表进行Θ(nlogn+n)预处理.Θ(1)查询.但是很不幸,如果直接用两个表分别存储最大值和最小值,最后一个点妥妥的MLE,因此我们需要对空间占用进行优化. 考虑到每个序列的长度是固定的,我们可以先进行一次ST表操作,记录下vali= max{ai →ai+m} .再在同一个f数组中进行第二次ST表操作,计算出fi = min{ai →

BZOJ 1342 Baltic2007 Sound静音问题 单调队列

题目大意:给定一个长度为n的序列,求哪些长度为m的区间满足区间内最大值与最小值之差小于等于c 利用单调队列维护区间内的最大值和最小值- - 硬搞就可以了- - 刷刷水题真爽- - #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 1001001 using namespace std; int n,m,c,a[M]; int q_ma

BZOJ1342 [Baltic2007]Sound静音问题

越来越水了... 这道题是简单的单调队列,同时维护最大值和最小值即可. 另解:multiset大法求区间最大最小,但是复杂度会上升... 1 /************************************************************** 2 Problem: 1342 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:944 ms 7 Memory:12524 kb 8 ***************

【单调队列】BZOJ1342-[Baltic2007]Sound静音问题

[题目大意] 给出一个n个数的序列,以哪位位置为开头的长度为m的区间满足该区间的最大值与最小值的差≤一个定值. [思路] 单调队列--说一下单调队列比较方便的操作. 把第一个先丢进去,开始条件为head=tail=1.就OK了.我以前总是喜欢左闭右开,还是都闭合好了不容易写错QAQ 所以--越刷越水,去睡觉! 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=1000000+50; 4 int maxque[MA

【尺取法】【Multiset】bzoj1342 [Baltic2007]Sound静音问题

O(n)地枚举所有长度为k的段,每次暴力转移. 转移的时候只是从最后插入一个数,从前面删去一个数. 计算的时候要取当前的max和min. 用multiset(∵元素是可重的)以上这些操作都是O(logn)的. 1 #include<cstdio> 2 #include<set> 3 using namespace std; 4 multiset<int>S; 5 multiset<int>::iterator it; 6 int n,m,limit; boo

【BZOJ1342】【Baltic2007】Sound静音问题 单调队列

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/42971677"); } 题意: 虽然这道题是汉语的,但是我有必要说一下题意. 就是问你长度为m的区间中,有哪些区间的最大值-最小值<=c,输出这个区间的左端点. 注意!!!如果没有方案输出NONE. 题解: 首先我们可以写一个multiset2