看到n <= 50000就要有莫队的敏感度。
某infleaking说也许整体二分套个数据结构是行的。
离散一下,直接莫队,用个常数小的树状数组维护一下就行了。
理论复杂度: O(nn√ log n)≈1.6∗109 。
加上那么一点小常数也许会T。
可是我才跑了1.6s,时限4s,……
Code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define low(x) ((x) & -(x))
using namespace std;
const int N = 5e4 + 5;
int n, k, Q, a[N];
struct node {
int i, x;
} b[N];
struct Ask {
int i, l, r;
} c[N];
const int M = 223;
int num[N], to[N];
int st[N], en[N];
bool rank(node a, node b) {return a.x < b.x;}
void Build() {
num[0] = 0;
fo(i, 1, n) {
num[i] = num[i - 1];
if((i - 1) % M == 0) num[i] ++;
}
}
void Build_se() {
fo(i, 1, n) {
int z = b[i].i;
for(int x = 1, y = i; x <= y; ) {
int m = x + y >> 1;
if(b[i].x - b[m].x <= k)
st[z] = m, y = m - 1; else x = m + 1;
}
for(int x = i, y = n; x <= y; ) {
int m = x + y >> 1;
if(b[m].x - b[i].x <= k)
en[z] = m, x = m + 1; else y = m - 1;
}
}
}
bool rank_c(Ask a, Ask b) {
if(num[a.l] < num[b.l]) return 1;
if(num[a.l] > num[b.l]) return 0;
return a.r < b.r;
}
int bz[N], f[N], ans[N], sum;
void add(int x, int y) {while(x <= n) f[x] += y, x += low(x);}
int qiu(int x) {int s = 0; while(x) s += f[x], x -= low(x); return s;}
int Sum(int x, int y) {return qiu(y) - qiu(x - 1);}
void chan(int x) {
int f = bz[x] ? -1 : 1; bz[x] = !bz[x];
if(f == -1) {
add(to[x], f);
sum += f * Sum(st[x], en[x]);
} else {
sum += f * Sum(st[x], en[x]);
add(to[x], f);
}
}
int main() {
scanf("%d %d %d", &n, &k, &Q);
fo(i, 1, n) scanf("%d", &a[i]), b[i].i = i, b[i].x = a[i];
sort(b + 1, b + n + 1, rank);
fo(i, 1, n) to[b[i].i] = i;
Build();
Build_se();
fo(i, 1, Q) scanf("%d %d", &c[i].l, &c[i].r), c[i].l ++, c[i].r ++, c[i].i = i;
sort(c + 1, c + Q + 1, rank_c);
int x = 1, y = 0;
fo(i, 1, Q) {
while(x < c[i].l) chan(x ++);
while(x > c[i].l) chan(-- x);
while(y < c[i].r) chan(++ y);
while(y > c[i].r) chan(y --);
ans[c[i].i] = sum;
}
fo(i, 1, Q) printf("%d\n", ans[i]);
}