题意:一个长度为N的正整数数组A,给出一个数K以及Q个查询,每个查询包含2个数l和r,对于每个查询输出从A[i]到A[j]中,有多
少对数,abs(A[i] - A[j]) <= K(abs表示绝对值)。
(2 <= N <= 50000, 0 <= K <= 10^9, 1 <= Q <= 50000,1 <= A[i] <= 10^9,0 <= l <= r < N)
思路:看到询问区间内满足条件的对数,容易想到莫队,条件是abs(A[i] - A[j]) <= K, 所以我们每次add或del时只要统计a[i]-K到a[i]+K之间有多少数就行,这样实现了logn的转移。所以复杂度是n*sqrt(n)*log(n). 因为a[i]比较大,所以需要离散化.
代码:
#include<bits/stdC++.h> using namespace std; typedef long long ll; const int maxn = 1e5+5; const int maxm = 4*maxn; int Hash[maxm], tree[maxm]; int n, k, q, cnt, unit, a[maxn], aa[maxn], al[maxn], ar[maxn]; ll tmp; ll ans[maxn]; struct node { int id, l, r, blk; bool operator < (const node &a) const { if(blk == a.blk) return r < a.r; else return blk < a.blk; } }op[maxn]; int lowbit(int x) { return x&(-x); } void update(int pos, int val) { while(pos < maxm) { tree[pos] += val; pos += lowbit(pos); } } int query(int pos) { int res = 0; while(pos) { res += tree[pos]; pos -= lowbit(pos); } return res; } void add(int x) { int t = 0; t += query(aa[x])-query(al[x]-1); t += query(ar[x])-query(aa[x]); tmp += t; update(aa[x], 1); } void del(int x) { int t = 0; update(aa[x], -1); t += query(aa[x])-query(al[x]-1); t += query(ar[x])-query(aa[x]); tmp -= t; } void solve() { memset(tree, 0, sizeof(tree)); tmp = 0; int l = 1, r = 0; for(int i = 1; i <= q; i++) { while(r < op[i].r) add(++r); while(r > op[i].r) del(r--); while(l < op[i].l) del(l++); while(l > op[i].l) add(--l); ans[op[i].id] = tmp; } for(int i = 1; i <= q; i++) printf("%lld\n", ans[i]); } int main(void) { while(cin >> n >> k >> q) { cnt = 0; unit = (int)sqrt(n); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); Hash[cnt++] = a[i]; Hash[cnt++] = a[i]-k; Hash[cnt++] = a[i]+k; } sort(Hash, Hash+cnt); int d = unique(Hash, Hash+cnt)-Hash; for(int i = 1; i <= n; i++) aa[i] = lower_bound(Hash, Hash+d, a[i])-Hash+1; for(int i = 1; i <= n; i++) al[i] = lower_bound(Hash, Hash+d, a[i]-k)-Hash+1; for(int i = 1; i <= n; i++) ar[i] = lower_bound(Hash, Hash+d, a[i]+k)-Hash+1; for(int i = 1; i <= q; i++) { scanf("%d%d", &op[i].l, &op[i].r); op[i].l++, op[i].r++; op[i].id = i, op[i].blk = op[i].l/unit; } sort(op+1, op+1+q); solve(); } return 0; } /* 5 2 3 1 3 4 3 0 0 1 1 3 0 4 */

本文介绍了一个涉及莫队算法的问题,具体是在一个整数数组中,针对一系列查询区间,计算每一对元素之间的绝对值差不超过给定阈值的数量。通过离散化和数据结构优化,实现高效的区间查询。
403

被折叠的 条评论
为什么被折叠?



