【洛谷P4392】 [BOI2007]Sound 静音问题
Description
给定一个序列和静音段,最大值和最小值之差不超过一个特定的阈值c,输出每行示一段静音的起始位置,按照出现的先后顺序输出。如果没有静音则输出NONE。
solution
利用线段树维护区间最大值和最小值,再枚举每个静音段的开始位置,如果区间中的最大值和最小值的差不超过c,就输出
Code
#include <bits/stdc++.h> const int N = 1e6 + 10; using namespace std; int n, m, c; int ma, mi = N; int a[N]; struct emmm { int l, r, maxn, minn; #define l(x) tr[x].l #define r(x) tr[x].r #define maxn(x) tr[x].maxn #define minn(x) tr[x].minn } tr[N << 2]; void build(int p, int l, int r) { l(p) = l; r(p) = r; if (l == r) { maxn(p) = minn(p) = a[l]; return ; } int mid = (l + r) >> 1; build(p << 1, l, mid); build(p << 1 | 1, mid + 1, r); maxn(p) = max(maxn(p << 1), maxn(p << 1 | 1)); minn(p) = min(minn(p << 1), minn(p << 1 | 1)); } void query(int p, int l, int r) { if (l <= l(p) && r >= r(p)) { ma = max(ma, maxn(p)); mi = min(mi, minn(p)); return ; } int mid = (l(p) + r(p)) >> 1; if (l <= mid) query(p << 1, l, r); if (r > mid) query(p << 1 | 1, l, r); } int main() { scanf("%d%d%d", &n, &m, &c); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); build(1, 1, n); bool flag = 0; for (int i = 1; i + m - 1 <= n; i++) { query(1, i, i + m - 1); if (ma - mi <= c) { flag = 1; cout << i << endl; } ma = 0; mi = N; } if (!flag) cout << "NONE" ; return 0; }