B
提供一个比较简单实现的思路
首先一个数在这个区间是第
大,等价于有
个数是小于等于这个数的
我们不妨将所有小于等于的数都变成1,将所有大于
的数都变成0
这样通过查询区间的和,就能判断是否有
个数小于等于
通过前缀和算法,可以加速查询,问题转化成了有多少个,满足
由于原数组是一个的排列,所以
只会出现一次,设它的位置是
我们令从
开始遍历,对于每个
,我们想知道有多少
,这个查询可以用
map
预处理出来
时间复杂度
#include <iostream> #include <cstring> #include <algorithm> #include <map> #define int long long using namespace std; typedef long long ll; const int N = 200005; ll a[N], b[N]; ll n, x, k; map<ll, ll> mp; signed main() { scanf("%lld%lld%lld", &n, &x, &k); int pos ; for(int i = 1; i <= n; i ++ ) { scanf("%lld", &a[i]); if(a[i] == x) pos = i; if(a[i] <= x) b[i] = 1; else b[i] = 0; } mp[0] ++ ; for(int i = 1; i <= n; i ++ ) { b[i] = b[i - 1] + b[i]; if(i < pos) mp[b[i]] ++ ; } int cnt = 0; for(int i = pos; i <= n; i ++ ) { cnt += mp[b[i] - k]; } cout << cnt; return 0; }