题解:AT_abc444_e [ABC444E] Sparse Range
分析性质
- 我们发现
l 从后往前枚举r 是单调不递增的,所以我们可以进行双指针。 - 我们发现满足题目条件的充要条件是任意两个
[a_i-d+1,a_i+d-1] 区间是不相交的,其中i 在区间[l,r] 中,所以我们可以使用线段树进行维护。
其他问题
记得离散化。
Code
所以代码如下:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 4e5+10;
const int inf = 2e9;
int n, a[N], d;
int b[N], c[N];
int p[N], q[N];
int sum[4*N];
void doChange(int k, int l, int r, int x, int dx) {
if (r < x || x < l) return ;
if (l == r) {
sum[k] += dx;
return ;
}
int mid = (l + r) >> 1;
doChange(k*2, l, mid, x, dx);
doChange(k*2+1, mid+1, r, x, dx);
sum[k] = sum[k*2]+sum[k*2+1];
}
int doQuery(int k, int l, int r, int x, int y) {
if (r < x || y < l) return 0;
if (x <= l && r <= y) return sum[k];
int mid = (l + r) >> 1;
return doQuery(k*2, l, mid, x, y) + doQuery(k*2+1, mid+1, r, x, y);
}
signed main() {
cin >> n >> d;
for (int i = 1;i<= n;i++) {
cin >> a[i], b[i] = a[i];
}
sort(b+1, b+n+1);
// 进行离散化
int m = unique(b+1, b+n+1)-b-1;
for (int i = 1;i<= n;i++) {
c[i] = lower_bound(b+1, b+m+1, a[i])-b;
}
for (int i = 1;i<= n;i++) {
int l = a[i]-d+1, r = a[i]+d-1;
l = lower_bound(b+1, b+m+1, l)-b, r = upper_bound(b+1, b+m+1, r)-b-1;
if (r < l) r = l;
p[i] = l, q[i] = r;
}
int ans = 0;
int l = n, r = n;
while (l >= 1) {
while (r - 1 >= l && doQuery(1, 1, n, p[l], q[l]) >= 1) { // 判断不合法
doChange(1, 1, n, c[r], -1);
r--;
}
doChange(1, 1, n, c[l], 1);
ans += (r-l+1);
l--;
}
cout << ans << endl;
return 0;
}