[Baltic2007]Sound静音问题

Description
序列中的每个元素是一个声音采样点
静音段的定义如下:
长度是m
段内最大采样值与最小采样值之差不超过阈值c
给定序列(长度n),m和c,求序列中的静音段

Input
第一行有三个整数n,m,c
1<= n<=1000000,1<=m<=10000,0<=c<=10000
分别表示总的采样数、静音的长度和静音中允许的最大噪音程度(即阈值)
第2行n个整数ai (0 <= ai <= 1,000,000),表示声音的每个采样值,每两个整数之间用空格隔开

Output
列出了所有静音的起始位置i(i满足max(a[i, … , i+m?1]) - min(a[i, … , i+m?1]) <= c)
每行表示一段静音的起始位置,按照出现的先后顺序输出。
如果没有静音直接输出NONE。

Sample Input
7 2 0
0 1 1 2 3 2 2

Sample Output
2
6

HINT
单调队列

题解
这道题其实就是求序列内每一段长度固定的区间的最大值与最小值之差。
于是就是很裸的单调队列题了。
单调队列实现方法可参考这里
别人的博客,写的不错。至少比我写的好

代码

#include <cstdio>

const int maxn=1000000;

struct str
{
    int val[maxn+10],pos[maxn+10],head,tail;
};

str minq,maxq;
int a[maxn+10];
int flag,n,m,c,i,j;

int main()
{
    maxq.head=1;
    minq.head=1;
    scanf("%d%d%d",&n,&m,&c);
    for (i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for (i=1;i<=n;i++)
    {
        while ((maxq.val[maxq.tail]<a[i])&&(maxq.head<=maxq.tail))
        {
            maxq.tail--;
        }//满足单调不上升
        maxq.tail++;
        maxq.val[maxq.tail]=a[i];
        maxq.pos[maxq.tail]=i;//向队尾添加元素
        while ((maxq.pos[maxq.head]<i-m+1)&&(maxq.head<=maxq.tail))
        {
            maxq.head++;
        }//去除已经不在区间内的情况
        //下面是维护单调不下降的队列,与上面一样
        while ((minq.val[minq.tail]>a[i])&&(minq.head<=minq.tail))
        {
            minq.tail--;
        }
        minq.tail++;
        minq.val[minq.tail]=a[i];
        minq.pos[minq.tail]=i;
        while ((minq.pos[minq.head]<i-m+1)&&(minq.head<=minq.tail))
        {
            minq.head++;
        }
        if (maxq.val[maxq.head]-minq.val[minq.head]<=c)//现在两个队列头就是最大值和最小值
        {
            if (i-m+1>0)
            {
                printf("%d\n",i-m+1);
                flag=1;
            }
        }
    }
    //上面全部是单调队列内容
    if (!flag)
    {
        printf("NONE\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值