区间绝对值小于k的数对(莫队+树状数组)
一个长度为N的正整数数组A,给出一个数K以及Q个查询,每个查询包含2个数l和r,对于每个查询输出从A[i]到A[j]中,有多少对数,abs(A[i] - A[j]) <= K(abs表示绝对值)。
输入
第1行:3个数N,K,Q,中间用空格分隔,N为数组A的长度,K为差距,Q为查询的数量。(2 <= N <= 50000, 0 <= K <= 10^9, 1 <= Q <= 50000) 第2至N + 1行:每行1个数,对应数组中的数(1 <= A[i] <= 10^9) 第N + 2至N + M + 1行:每行2个数l, r中间用空格分隔(0 <= l <= r < N)
输出
输出共Q行,对于Q条查询的结果。
输入样例
5 2 3
1
3
4
3
0
0 1
1 3
0 4
输出样例
1 3 6
只需要考虑加入一个数会产生多少贡献即可
离散化的时候把 ai,ai−k,ai+k全部放进去。
加入一个数的时候只需要维护 [ai−k,ai+k] 有多少个数,并且把 aiai 这个位置加上 1
删除亦然。这个可以用树状数组方便地维护。
具体实现的时候,因为树状数组是 sum(r) - sum(l-1) ,所以可以直接把 ai,ai−k−1,ai+k放进去离散化,求贡献就不用 -1 了
总复杂度 O(n−−√logn)
#include<iostream> #include<algorithm> #include<math.h> using namespace std; const int maxn=1e6+100; struct node1{ int lv,rv,v; }a[maxn]; int belong[maxn]; int res[maxn]; int id[maxn]; int c[maxn],n,m,k,mx; int lowbit(int x){ return x&-x; } void add(int x,int k){ for(int i=x;i<=mx;i+=lowbit(i)){ c[i]+=k; } } int sum(int x){ int ans=0; for(int i=x;i>0;i-=lowbit(i)){ ans+=c[i]; } return ans; } struct node{ int l,r,id; }q[maxn]; bool cmp(node x,node y){ if(belong[x.l]!=belong[y.l]){ return belong[x.l]<belong[y.l]; } else{ if(belong[x.l]&1){ return x.r<y.r; } else{ return x.r>y.r; } } } int cnt=0; int now=0; void ADD(int pos){ now+=(sum(a[pos].rv)-sum(a[pos].lv));//因为自己不算,所以要先加在,莫队修改 add(a[pos].v,1); } void remove(int pos){ add(a[pos].v,-1);//先删除在加 now-=(sum(a[pos].rv)-sum(a[pos].lv)); } int main(){ cin>>n>>k>>m; int block=sqrt(n); for(int i=1;i<=n;i++){ cin>>a[i].v; a[i].lv=(a[i].v-k-1); a[i].rv=(a[i].v+k); belong[i]=(i-1)/block+1; id[++cnt]=a[i].lv; id[++cnt]=a[i].v; id[++cnt]=a[i].rv; } sort(id+1,id+cnt+1); int len=unique(id+1,id+cnt+1)-(id+1); for(int i=1;i<=n;i++){ a[i].v=lower_bound(id+1,id+len+1,a[i].v)-id; a[i].lv=lower_bound(id+1,id+len+1,a[i].lv)-id; a[i].rv=lower_bound(id+1,id+len+1,a[i].rv)-id; mx=max(mx,a[i].rv); } for(int i=1;i<=m;i++){ cin>>q[i].l>>q[i].r; q[i].l++; q[i].r++; q[i].id=i; } sort(q+1,q+m+1,cmp); int l=1,r=0; for(int i=1;i<=m;i++){ int ql=q[i].l,qr=q[i].r; while(l<ql){ remove(l++); } while(l>ql){ ADD(--l); } while(r>qr){ remove(r--); } while(r<qr){ ADD(++r); } res[q[i].id]=now; } for(int i=1;i<=m;i++){ cout<<res[i]<<endl; } }