区间绝对值小于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,aik,ai+k全部放进去。

加入一个数的时候只需要维护 [aik,ai+k] 有多少个数,并且把 aiai 这个位置加上 1

删除亦然。这个可以用树状数组方便地维护。

具体实现的时候,因为树状数组是 sum(r) - sum(l-1) ,所以可以直接把 ai,aik1,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;
    } 
}

 

posted @ 2021-05-02 14:24  lipu123  阅读(113)  评论(0编辑  收藏  举报