赞
踩
给定一个
n
n
n个数的序列
a
i
a_i
ai。有
q
q
q次询问,每次询问是一个非负整数
k
k
k,求出有多少对
(
l
,
r
)
(l, r)
(l,r),满足
m
a
x
(
a
[
i
]
)
−
m
i
n
(
a
[
j
]
)
>
k
max(a[i]) - min(a[j]) > k
max(a[i])−min(a[j])>k,其中
l
≤
i
,
j
≤
r
l\le i, j \le r
l≤i,j≤r。
题目链接
不难发现满足要求的序列有单调性,即如果当前区间满足最大值减去最小值大于k,那么包含这个区间的更大的区间,也一定满足。
而这一类问题,通常可以采用尺取法。即:
#include <cstdio> #include <iostream> #include <deque> #include <cstring> #include <algorithm> using namespace std; const int maxN = 1e5 + 7; typedef long long ll; int m, n, a[maxN]; ll calc(ll k) { deque<int> maxPos, minPos; int l = 1,r = 0; ll ans = 0; while(l <= n && r <= n) { while((!maxPos.empty()) && maxPos.front() < l) maxPos.pop_front(); while((!minPos.empty()) && minPos.front() < l) minPos.pop_front(); if((!maxPos.empty()) && a[maxPos.front()] - a[minPos.front()] > k) { ans += n - r + 1; ++l; continue; } else { ++r; while(!maxPos.empty() && a[maxPos.back()] <= a[r]) maxPos.pop_back(); maxPos.push_back(r); while(!minPos.empty() && a[minPos.back()] >= a[r]) minPos.pop_back(); minPos.push_back(r); } } return ans; } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); for(int i = 1; i <= m; ++i) { int k; scanf("%d", &k); printf("%lld\n", calc(k)); } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。