题意:
给你一个数组,对于第i个数来说,如果存在一个位置j,使得j>i并且a[j]-k<=a[i]<=a[j]+k,那么这对数就称为好的,有q个询问,问你l到r区间有多少对好的数。
题解:
有点像上次那道区间因子对数的题目,但是这道题不能用那种方法做,因为如果要维护消去前面的数影响后面数的位置的话,有可能是n*n的复杂度。但是可以用用莫队+树状数组做,离散化a[i]和a[i]+k和a[i]-k-1即可。
#include<bits/stdc++.h>
using namespace std;
const int N=27005;
int num[N*3];
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int val)
{
for(int i=x;i<N*3;i+=lowbit(i))
num[i]+=val;
}
int query(int x)
{
int ans=0;
for(int i=x;i;i-=lowbit(i))
ans+=num[i];
return ans;
}
int a[N],b[N*3],upa[N],downa[N];
struct node
{
int l,r,id;
}q[N];
int pos[N],ans[N];
bool cmp(node x,node y)
{
return pos[x.l]<pos[y.l]||pos[x.l]==pos[y.l]&&x.r<y.r;
}
int main()
{
int n,m,k,all=0;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),b[++all]=a[i],b[++all]=a[i]-k-1,b[++all]=a[i]+k;
sort(b+1,b+1+all);
all=unique(b+1,b+1+all)-b-1;
for(int i=1;i<=n;i++)
upa[i]=lower_bound(b+1,b+1+all,a[i]+k)-b,downa[i]=lower_bound(b+1,b+1+all,a[i]-k-1)-b,a[i]=lower_bound(b+1,b+1+all,a[i])-b;
int blog=sqrt(n);
for(int i=1;i<=n;i++)
pos[i]=(i-1)/blog+1;
for(int i=1;i<=m;i++)
scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
sort(q+1,q+1+m,cmp);
int l=q[1].l,r=q[1].l-1,sum=0;
for(int i=1;i<=m;i++)
{
while(r<q[i].r)
{
r++;
sum+=query(upa[r])-query(downa[r]);
add(a[r],1);
}
while(l>q[i].l)
{
l--;
sum+=query(upa[l])-query(downa[l]);
add(a[l],1);
}
while(r>q[i].r)
{
add(a[r],-1);
sum-=query(upa[r])-query(downa[r]);
r--;
}
while(l<q[i].l)
{
add(a[l],-1);
sum-=query(upa[l])-query(downa[l]);
l++;
}
ans[q[i].id]=sum;
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}