[BOI2007] Sound 静音问题
题目描述
数字录音中,声音是用表示空气压力的数字序列描述的,序列中的每个值称为一个采样,每个采样之间间隔一定的时间。
很多声音处理任务都需要将录到的声音分成由静音隔开的几段非静音段。为了避免分成过多或者过少的非静音段,静音通常是这样定义的: m m m 个采样的序列,该序列中采样的最大值和最小值之差不超过一个特定的阈值 c c c。
请你写一个程序,检测 n n n 个采样中的静音。
输入格式
第一行有三个整数 n , m , c n,m,c n,m,c( 1 ≤ n ≤ 1 0 6 1\le n\le10^6 1≤n≤106, 1 ≤ m ≤ 1 0 4 1\le m\le10^4 1≤m≤104, 0 ≤ c ≤ 1 0 4 0\le c\le10^4 0≤c≤104),分别表示总的采样数、静音的长度和静音中允许的最大噪音程度。
第 2 2 2 行 n n n 个整数 a i a_i ai( 0 ≤ a i ≤ 1 0 6 0\le a_i\le 10^6 0≤ai≤106),表示声音的每个采样值,每两个整数之间用空格隔开。
输出格式
列出了所有静音的起始位置
i
i
i(
i
i
i 满足
max
{
a
i
,
a
i
+
1
⋯
a
i
+
m
−
1
}
−
min
{
a
i
,
a
i
+
1
⋯
a
i
+
m
−
1
}
≤
c
\max\{a_i,a_{i+1}\cdots a_{i+m-1}\}-\min\{a_i,a_{i+1}\cdots a_{i+m-1}\}\le c
max{ai,ai+1⋯ai+m−1}−min{ai,ai+1⋯ai+m−1}≤c),每行表示一段静音的起始位置,按照出现的先后顺序输出。如果没有静音则输出 NONE
。
样例 #1
样例输入 #1
7 2 0
0 1 1 2 3 2 2
样例输出 #1
2
6
解析
线段树跑一遍,注意题意为全部的区间,可以重叠,i 不要跳转
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define L u<<1
#define R u<<1|1
#define inf 0x3f3f3f3f
const int N=1e6+5;
int n,m,c,a[N];
struct node{
int l,r;
int smax,smin;
}tr[N*4];
void build(int u,int l,int r){
tr[u].l=l,tr[u].r=r;
if(l==r){
tr[u].smax=tr[u].smin=a[l];
return;
}
int mid=l+r>>1;
build(L,l,mid),build(R,mid+1,r);
tr[u].smax=max(tr[L].smax,tr[R].smax);
tr[u].smin=min(tr[L].smin,tr[R].smin);
}
pair<int,int> query(int u,int l,int r){
if(tr[u].l>=l&&tr[u].r<=r)
return {tr[u].smax,tr[u].smin};
int mid=tr[u].l+tr[u].r>>1;
int tmax=0,tmin=inf;
if(l<=mid){
pair<int,int>p=query(L,l,r);
tmax=max(tmax,p.first);
tmin=min(tmin,p.second);
}
if(r>mid){
pair<int,int>p=query(R,l,r);
tmax=max(tmax,p.first);
tmin=min(tmin,p.second);
}
return {tmax,tmin};
}
void solve(){
scanf("%lld%lld%lld",&n,&m,&c);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
int f=1;
for(int i=1;i<=n-m+1;i++){
pair<int,int>ans=query(1,i,i+m-1);
if(ans.first-ans.second<=c){
printf("%lld\n",i);
f=0;
// i+=m-1; //此处不需要添加
}
}
if(f) puts("NONE");
}
signed main(){
int t=1;
// scanf("%d",&t);
while(t--) solve();
return 0;
}