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; }