【洛谷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;
}

 

posted @ 2019-08-29 17:08  _sheldon  阅读(255)  评论(0编辑  收藏  举报