题目
Sample Input
7 5 3
2 5 7 5 1 5 6
6 6
1 3
4 6
2 4
3 4
Sample Output
0
2
1
3
1
题意: 给一个大小为n的序列,和一个k。询问m个区间。问每个区间里可以找出多少个友对。
友对: i<j,| a[j]-a[i] |<k。
思路: a[j]-a[i]<k -----a[j]<a[i]+k a[i]-a[j]<k ---- a[i]-k<a[j]
则需要找到对于每个j满足 a[i]-k<a[j]<a[i]+k的个数。很简单就是树状数组维护权值+莫队。
记得离散化。离散化的值用数组先预处理存好。否则莫队每次修改时都要知道他的refl,要lower_bound会超时.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define m(a,b) memset(a,b,sizeof a)
#define en '\n'
#define low(i) i&-i
using namespace std;
typedef long long ll;
const int N=1e5+5,M=1e5+5;
template<class T>void rd(T &x)
{
x=0;int f=0;char ch=getchar();
while(ch<'0'||ch>'9') {f|=(ch=='-');ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return;
}
ll a[N],refl[N*3],c[N*3];
int dex[N*3],tot,n;
struct Query{int id,l,r;}q[M];
ll ans[N],res;
int dexl,dexr,block;
bool cmp(Query x,Query y)
{
if(x.l/block==y.l/block)
return x.r<y.r;
return x.l/block<y.l/block;
}
void modify(int i,int val)
{
for(;i<=n*3;i+=low(i))
c[i]+=val;
}
int getsum(int i)
{
int ans=0;
for(;i;i-=low(i))
ans+=c[i];
return ans;
}
void add(int x)
{
int l=dex[x+n],r=dex[x+n*2],w=dex[x];
res+=getsum(r)-getsum(l-1);
modify(w,1);//先统计再modify.否则会多考虑a[x]-a[x]=0,这种不合理配对情况。(x是同一个位置,a[x]=a[y]这种不同位置的本来就要考虑,已经在统计中考虑过"a[x]"这个值了)
}
void del(int x)
{
int l=dex[x+n],r=dex[x+n*2],w=dex[x];
modify(w,-1);
res-=getsum(r)-getsum(l-1);//同上,先统计的话会多减去a[x]-a[x]=0,这种不合理的情况.
}
int main()
{
int m,k;rd(n),rd(m),rd(k);block=sqrt(n);
for(int i=1;i<=n;i++)
{
rd(a[i]),a[i+n]=a[i]-k,a[i+n*2]=a[i]+k;
refl[i]=a[i],refl[i+n]=a[i]-k,refl[i+n*2]=a[i]+k;
}
sort(refl+1,refl+n*3+1);
tot=unique(refl+1,refl+n*3+1)-(refl+1);
for(int i=1;i<=n;i++)
{
dex[i]=lower_bound(refl+1,refl+tot+1,a[i])-refl;
dex[i+n]=lower_bound(refl+1,refl+tot+1,a[i+n])-refl;
dex[i+n*2]=lower_bound(refl+1,refl+tot+1,a[i+n*2])-refl;
}
for(int i=1;i<=m;i++)
rd(q[i].l),rd(q[i].r),q[i].id=i;
sort(q+1,q+m+1,cmp);
dexl=1,dexr=0,res=0;
for(int i=1;i<=m;i++)
{
while(dexr>q[i].r)
del(dexr--);
while(dexr<q[i].r)
add(++dexr);
while(dexl<q[i].l)
del(dexl++);
while(dexl>q[i].l)
add(--dexl);
ans[q[i].id]=res;
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}