题链:https://vjudge.net/problem/HDU-6534
题意:问区间[L,R]内,有多少对 (i,j) 满足 i < j 且 abs(ai-aj) <= k ?
思路:莫队分块一下,对于ai 要找的是有多少 ai-k <= aj <= ai+k ,树状数组求即可。
实现1:998ms直接无脑实现
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3e4+10;
int n,m,k,a[N];
struct node{
int l,r,id;
}q[N];
int block,be[N];
set<int> s;
set<int>::iterator it;
unordered_map<int,int> mp;
int Id=0;
int sum=0;
bool cmp(node a,node b){
return (be[a.l]^be[b.l]) ? be[a.l]<be[b.l] : (be[a.l]&1) ? a.r<b.r : a.r>b.r ;
}
int num[N*3],ans[N];
int lowbit(int x){ return x&(-x); }
void add1(int x,int val,int nn){
while(x<=nn){
num[x]+=val;
x+=lowbit(x);
}
return ;
}
int ask(int x){
int ans=0;
while(x){
ans+=num[x];
x-=lowbit(x);
}
return ans;
}
void del(int x){
add1(mp[a[x]],-1,Id);
sum-=(ask(mp[a[x]+k])-ask(mp[a[x]-k]-1));
}
void add(int x){
sum+=(ask(mp[a[x]+k])-ask(mp[a[x]-k]-1));
add1(mp[a[x]],1,Id);
}
int main(void){
scanf("%d%d%d",&n,&m,&k);
block=ceil(sqrt(1.0*n));
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
be[i]=i/block;
s.insert(a[i]);
s.insert(a[i]-k);
s.insert(a[i]+k);
}
for(it = s.begin();it!=s.end();it++)
mp[*it]=++Id;
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=1,r=0;
sum=0;
for(int i=1;i<=m;i++){
int ql=q[i].l,qr=q[i].r;
while(l<ql) del(l++);
while(l>ql) add(--l);
while(r<qr) add(++r);
while(r>qr) del(r--);
ans[q[i].id]=sum;
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}
实现1:202ms需要思考一下边界
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3e4+10;
int n,m,k,a[N];
struct node{
int l,r,id;
}q[N];
int block,be[N];
int Id=0;
int sum=0;
bool cmp(node a,node b){
return (be[a.l]^be[b.l]) ? be[a.l]<be[b.l] : (be[a.l]&1) ? a.r<b.r : a.r>b.r ;
}
int num[N],ans[N],b[N],pos[N][3];
int lowbit(int x){ return x&(-x); }
void add1(int x,int val,int nn){
while(x<=nn){
num[x]+=val;
x+=lowbit(x);
}
return ;
}
int ask(int x){
int ans=0;
while(x){
ans+=num[x];
x-=lowbit(x);
}
return ans;
}
void del(int x){
add1(pos[x][0],-1,Id);
sum-=(ask(pos[x][2])-ask(pos[x][1]));
}
void add(int x){
sum+=(ask(pos[x][2])-ask(pos[x][1]));
add1(pos[x][0],1,Id);
}
int main(void){
scanf("%d%d%d",&n,&m,&k);
block=ceil(sqrt(1.0*n));
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
be[i]=i/block;
}
sort(b+1,b+1+n);
//预处理
Id = unique(b+1,b+1+n)-(b+1);
for(int i=1;i<=n;i++){
pos[i][0]=lower_bound(b+1,b+1+Id,a[i])-b;
pos[i][1]=lower_bound(b+1,b+1+Id,a[i]-k)-b -1;
pos[i][2]=lower_bound(b+1,b+1+Id,a[i]+k)-b;
if(pos[i][2]>Id || b[pos[i][2]]>a[i]+k) pos[i][2]--;
//pos[i][2]=upper_bound(b+1,b+1+Id,a[i]+k)-b -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=1,r=0;
sum=0;
for(int i=1;i<=m;i++){
int ql=q[i].l,qr=q[i].r;
while(l<ql) del(l++);
while(l>ql) add(--l);
while(r<qr) add(++r);
while(r>qr) del(r--);
ans[q[i].id]=sum;
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}