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;
}