题目大意:给你一个长度为n的序列a(1<=n<=27000,1<=a[i]<=1e9),m(1<=m<=27000)个查询,k(1<=k<=1e9),每次查询给出li,ri。需要回答在[li,ri]这个区间内有多少对(i,j)满足i<j并且a[i]-a[j]<=k。
思路:题目没有要求在线做,并且又是这么多的区间询问,再看数据范围,显然可以用莫队做。因为莫队算法本身就是每次维护区间的边缘+1或者-1。所以对于一个区间,往最左边或最右边新加入一个数x,那么答案就会多出原来区间里数值大小在[x-k,x+k]范围的个数个。减少一个数同理。然后我们就可以用树状数组来维护个数。因为数值较大需要离散化。
AC代码:
//#include<bits/stdc++.h> #include<set> #include<map> #include<stack> #include<cmath> #include<ctime> #include<queue> #include<cstdio> #include<string> #include<vector> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; typedef pair<ll, ll> pll; typedef pair<ll, int> pli; typedef pair<int, ll> pil; #define pb push_back #define X first #define Y second inline ll gcd(ll a, ll b) { while (b != 0) { ll c = a % b; a = b; b = c; }return a < 0 ? -a : a; } inline ll lcm(ll a, ll b) { return (a * b) / gcd(a, b); } inline ll lowbit(ll x) { return x & (-x); } const double PI = 3.14159265358979323846; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; const ll mod = 1e9 + 7; inline char nc() { static char buf[1 << 21], * p1 = buf, * p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; } inline ll rd() { //#define getchar nc ll x = 0, f = 1; char ch = getchar(); while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); } return x * f; } const double eps = 1e-6; const int M = 1e6 + 10; const int N = 1e5 + 10; int a[N]; int n, m, k; int maxx; vector<int>v; int b[N]; void discreat() { for (int i = 1; i <= n; i++)v.pb(a[i]); sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); maxx = v.size(); for (int i = 1; i <= maxx; i++)b[i] = v[i - 1]; } inline int getid(int x) { return lower_bound(b + 1, b + 1 + maxx, x) - b; } int nl, nr; ll now; int S; struct MM { int id, l, r, bk; bool friend operator<(const MM& m1, const MM& m2) { if (m1.bk != m2.bk)return m1.bk < m2.bk; return m1.r < m2.r; } }qr[N]; int c[N]; inline void update(int x, int y) { for (; x <= maxx; x += lowbit(x)) { c[x] += y; } } inline int query_sum(int x) { int sum = 0; for (; x > 0; x -= lowbit(x)) { sum += c[x]; } return sum; } int L[N], R[N]; inline int get(int x) { if (L[x] > R[x])return 0; return query_sum(R[x]) - query_sum(L[x] - 1); } int has[N]; inline void add(int x) { now += 1ll * get(x); update(has[x], 1); } inline void del(int x) { update(has[x], -1); now -= 1ll * get(x); } inline void move(int tl, int tr) { while (nr < tr)add(++nr); while (nl > tl)add(--nl); while (nr > tr)del(nr--); while (nl < tl)del(nl++); } ll ans[N]; int main() { n = rd(), m = rd(), k = rd(); for (int i = 1; i <= n; i++)a[i] = rd(); S = n / sqrt(m); discreat(); for (int i = 1; i <= n; i++)has[i] = getid(a[i]); for (int i = 1; i <= n; i++) { L[i] = lower_bound(b + 1, b + 1 + maxx, a[i] - k) - b; R[i] = lower_bound(b + 1, b + 1 + maxx, a[i] + k) - b; if (R[i] == maxx + 1 || b[R[i]] > a[i] + k)R[i]--; } for (int i = 1; i <= m; i++) { qr[i].l = rd(), qr[i].r = rd(); qr[i].id = i; qr[i].bk = (qr[i].l - 1) / S; } sort(qr + 1, qr + 1 + m); nl = 1, nr = 0, now = 0; for (int i = 1; i <= m; i++) { move(qr[i].l, qr[i].r); ans[qr[i].id] = now; } for (int i = 1; i <= m; i++)printf("%lld\n", ans[i]); }