题解 :单调队列维护窗口的最大值和最小值 然后查询即可
#include <bits/stdc++.h> const int MAXN=2e6+10; using namespace std; int a[MAXN],q[MAXN],qh,qt; int mn[MAXN],mx[MAXN]; int main(){ int n,m,c;scanf("%d%d%d",&n,&m,&c); qh=1;qt=0; for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=m-1;i++){ while(qh<=qt&&a[q[qt]]>=a[i])qt--; q[++qt]=i; } for(int i=m;i<=n;i++){ while(qh<=qt&&i-q[qh]>=m)qh++; while(qh<=qt&&a[q[qt]]>=a[i])qt--; q[++qt]=i; mn[i-m+1]=a[q[qh]]; } qh=1;qt=0; for(int i=1;i<=m-1;i++){ while(qh<=qt&&a[q[qt]]<=a[i])qt--; q[++qt]=i; } for(int i=m;i<=n;i++){ while(qh<=qt&&i-q[qh]>=m)qh++; while(qh<=qt&&a[q[qt]]<=a[i])qt--; q[++qt]=i; mx[i-m+1]=a[q[qh]]; } bool flag=0; for(int i=1;i<=n-m+1;i++){ if(mx[i]-mn[i]<=c)flag=1,printf("%d ",i); } if(!flag)printf("NONE "); return 0; }
1342: [Baltic2007]Sound静音问题
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 1043 Solved: 470
[Submit][Status][Discuss]
Description
数字录音中,声音是用表示空气压力的数字序列描述的,序列中的每个值称为一个采样,每个采样之间间隔一定的
时间。 很多声音处理任务都需要将录到的声音分成由静音隔开的几段非静音段。为了避免分成过多或者过少的非
静音段,静音通常是这样定义的:m个采样的序列,该序列中采样的最大值和最小值之差不超过一个特定的阈值c。
请你写一个程序,检测n个采样中的静音。
Input
第一行有三个整数n,m,c,分别表示总的采样数、静音的长度和静音中允许的最大噪音程度。
第2行n个整数ai,表示声音的每个采样值,每两个整数之间用空格隔开。
1<=n<=1000000,1<=m<=10000,0<=c<=10000
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
0 1 1 2 3 2 2
Sample Output
2
6
6