51nod 1275 连续子段的差异

题目看这里

若[i,j]符合要求,那么[i,j]内的任何连续的子段都是符合要求的。我们可以枚举i,找到能合格的最远的j,然后ans+=(j-i+1)。

那么问题就转换成了:在固定i的情况下,如何判断j范围内是否合法?若[i,j]内的max-min<=K自然就合法。于是相当于求区间内的最值问题。这个可以用单调队列解决。

下面对代码给出一些解释:

1:为何是j-i而非j-i+1?因为当不合法时区间相当于[i,j),左闭右开,数量是i-j即可。

2:后面的两行如if (dqB.front() == i) dqB.pop_front(); 什么作用?因为要枚举i,所以到了下一个i的时候,若前面的i还在队列中,要去掉。

#include <bits/stdc++.h>
using namespace std;

const int maxN=5e4+5;
int N, M, K, T;
int g[maxN];
deque<int> dqB, dqS;

int main() {
#ifndef ONLINE_JUDGE
    freopen("data.in", "r", stdin);
#endif
    scanf("%d%d", &N, &K);
    for (int i = 1; i <= N; ++i)
        scanf("%d", g + i);
    int ans = 0;
    for (int i = 1, j = 1; i <= N; ++i) {
        while (j <= N) {
            while (dqS.size() && g[dqS.back()] >= g[j]) dqS.pop_back();
            dqS.push_back(j);
            while (dqB.size() && g[dqB.back()] <= g[j]) dqB.pop_back();
            dqB.push_back(j);

            if (g[dqB.front()] - g[dqS.front()] > K)
                break;
            ++j;
        }
        ans += (j - i);
        if (dqS.front() == i) dqS.pop_front();
        if (dqB.front() == i) dqB.pop_front();
    }
    printf("%d", ans);
    return 0;
}

附上别的相关的博客

posted @ 2018-08-24 18:51  gaawing  阅读(218)  评论(0编辑  收藏  举报