P4392 [BOI2007]Sound 静音问题
题目描述
数字录音中,声音是用表示空气压力的数字序列描述的,序列中的每个值称为一个采样,每个采样之间间隔一定的时间。
很多声音处理任务都需要将录到的声音分成由静音隔开的几段非静音段。为了避免分成过多或者过少的非静音段,静音通常是这样定义的:m个采样的序列,该序列中采样的最大值和最小值之差不超过一个特定的阈值c。
请你写一个程序,检测n个采样中的静音。
输入格式
第一行有三个整数n,m,c( 1<= n<=1000000,1<=m<=10000, 0<=c<=10000),分别表示总的采样数、静音的长度和静音中允许的最大噪音程度。
第2行n个整数ai (0 <= ai <= 1,000,000),表示声音的每个采样值,每两个整数之间用空格隔开。
输出格式
列出了所有静音的起始位置i(i满足max(a[i, . . . , i+m−1]) − min(a[i, . . . , i+m−1]) <= c),每行表示一段静音的起始位置,按照出现的先后顺序输出。如果没有静音则输出NONE。
输入输出样例
输入 #1
7 2 0 0 1 1 2 3 2 2
输出 #1
2 6
思路
根据题目来:1.先维护区间的最大以及最小,然后向里面添加数(一次一个)2.求和 3.完结撒花✿✿ヽ(°▽°)ノ✿
代码
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=1000010; int n,m,ci,cnt; int ans[N],a[N]; struct no { int a; int mx=-0x7f7f7f7f,mn=0x7f7f7f7f; } c[2*N]; int lowbit(int x) { return x&(-x); } void add(int p,int x) { for(; p<=n; p+=lowbit(p)) { c[p].mx=max(c[p].mx,x); c[p].mn=min(c[p].mn,x); } } bool sum(int l,int r) { int mx=-0x7f7f7f7f,mn=0x7f7f7f7f; while(l<=r) { for(; r-lowbit(r)>=l; r-=lowbit(r)) { mx=max(c[r].mx,mx); mn=min(c[r].mn,mn); } mx=max(a[r],mx); mn=min(a[r],mn); r--; } if(abs(mx-mn)<=ci) return true; return false; } int main () { scanf("%d%d%d",&n,&m,&ci); for(int i=1; i<=n; i++) { int x; scanf("%d",&a[i]); add(i,a[i]); } for(int i=1; i<=n-m+1; i++) if(sum(i,i+m-1)) ans[++cnt]=i; for(int i=1; i<=cnt; i++) printf("%d\n",ans[i]); if(cnt==0) printf("NONE\n"); return 0; }