Chika and Friendly Pairs
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 874 Accepted Submission(s): 308
Problem Description
Chika gives you an integer sequence a1,a2,…,an and m tasks. For each task, you need to answer the number of "friendly pairs" in a given interval.
friendly pair: for two integers ai and aj, if i<j and the absolute value of ai−aj is no more than a given constant integer K, then (i,j) is called a "friendly pair".A friendly pair (i,j) in a interval [L,R] should satisfy L≤i<j≤R.
Input
The first line contains 3 integers n (1≤n≤27000), m (1≤m≤27000) and K (1≤K≤109), representing the number of integers in the sequence a, the number of tasks and the given constant integer.
The second line contains n non-negative integers, representing the integers in the sequence a. Every integer of sequence a is no more than 109.
Then m lines follow, each of which contains two integers L, R (1≤L≤R≤n). The meaning is to ask the number of "friendly pairs" in the interval [L,R]。
Output
For each task, you need to print one line, including only one integer, representing the number of "friendly pairs" in the query interval.
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
Source
离散化+预处理+莫队+树状数组
输入n个a[i],对 a[i]-k, a[i], a[i]+k进行离散化+去重,存到b数组中
预处理 a[i]-k, a[i], a[i]+k 在b数组中的位置,分别存到down, a, up数组中
输入m个区间,存到结构体中,按照莫队算法进行排序
之后用树状数组维护a[i]的位置,两次query查询a[i]-k到a[i]+k区间中有多少数
(表述的有点问题,大致就是这个意思,看代码就好了,不喜勿喷)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 27005
int c[N*3], a[N], b[N*3], up[N], down[N];
int n, m, k, pos[N], ans[N];
struct node{
int id, l, r;
}no[N];
bool cmp(node a, node b){
if(pos[a.l]==pos[b.l]) return a.r<b.r;
return pos[a.l]<pos[b.l];
}
int lowbit(int x){
return x&(-x);
}
void add(int x, int val){
while(x<=n*3){
c[x]+=val;
x+=lowbit(x);
}
}
int query(int x){
int ret=0;
while(x){
ret+=c[x];
x-=lowbit(x);
}
return ret;
}
int main()
{
int i, blog, tot=0;
scanf("%d%d%d",&n,&m,&k);
blog=sqrt(n);
for(i=1;i<=n;++i) pos[i]=(i-1)/blog+1;
for(i=1;i<=n;++i){
scanf("%d",&a[i]);
b[++tot]=a[i]-k;
b[++tot]=a[i];
b[++tot]=a[i]+k;
}
sort(b+1,b+tot+1);
tot=unique(b+1,b+tot+1)-b-1;
for(i=1;i<=n;++i){
up[i]=lower_bound(b+1,b+tot+1,a[i]+k)-b;
down[i]=lower_bound(b+1,b+tot+1,a[i]-k)-b;
a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
}
for(i=1;i<=m;++i)
scanf("%d%d",&no[i].l,&no[i].r), no[i].id=i;
sort(no+1,no+m+1,cmp);
int l=no[1].l, r=l-1, sum=0;
for(i=1;i<=m;++i){
while(r<no[i].r){
++r;
sum+=query(up[r])-query(down[r]-1);
add(a[r],1);
}
while(l>no[i].l){
--l;
sum+=query(up[l])-query(down[l]-1);
add(a[l],1);
}
while(r>no[i].r){
add(a[r],-1);
sum-=query(up[r])-query(down[r]-1);
--r;
}
while(l<no[i].l){
add(a[l],-1);
sum-=query(up[l])-query(down[l]-1);
++l;
}
ans[no[i].id]=sum;
}
for(i=1;i<=m;++i) printf("%d\n",ans[i]);
return 0;
}