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
题意:
在给定一个区间中找出 |a[i]-a[j] |<=k (i<j)的对数.
思路:
首先考虑用莫队优雅暴力求解。
那么如何求解区间内对数呢?
如果暴力查找区间内符合条件的个数肯定会超时(O(n^2)) ,那么就直接查询区间内大于等于a[i]-k和小于等于a[i]+k的个数就行了。于是采用树状数组来维护每个值的个数,由于a[i]<=1e9,所以要离散化一下。每次增加和删除操作通过查询上下界,然后求出[L, R]内的和。需要注意的是上界可能会是N+1或者对应的值大于计算出的上界,所以对此要特判减1。
本以为这样就可以过了,结果还是TLE了。。。
好吧,如果每次在增加删除操作里面求上下界,会有许多重复计算,所以先预处理出每个数值的上下界及每个数对应的离散化值。终于过了。。。。。。
代码:
#include<bits/stdc++.h>
using namespace std;
const int Ms=27001;
struct node
{
int l,r,id;
}q[Ms],FL[Ms];
int ans[Ms],T[Ms],a[Ms],b[Ms],N,k,block[Ms],res,hs[Ms];
bool cmp(node a,node b)
{
if(block[a.l]!=block[b.l])return block[a.l]<block[b.l];
return a.r<b.r;
}
int get_id(int x)
{
return lower_bound(b+1,b+N+1,x)-b;
}
int lowbit(int x)
{
return x&(-x);
}
void up(int x,int val)
{
while(x<=N)
{
T[x]+=val;
x+=lowbit(x);
}
}
int query(int x)
{
int re=0;
while(x>0)
{
re+=T[x];
x-=lowbit(x);
}
return re;
}
void add(int pos)
{
int h=hs[pos],l=FL[h].l,r=FL[h].r;
res+=query(r)-query(l-1);
up(h,1);
}
void del(int pos)
{
int h=hs[pos],l=FL[h].l,r=FL[h].r;
up(h,-1);
res-=query(r)-query(l-1);
}
void cake(int n)
{
int l,r;
for(int i=1;i<=n;i++)
{
hs[i]=get_id(a[i]);
if(FL[hs[i]].l==0)
{
l=get_id(a[i]-k);r=get_id(a[i]+k);
if(r==N+1)r--;
if(b[r]>a[i]+k)r--;
FL[hs[i]].l=l;FL[hs[i]].r=r;
}
}
}
int main()
{
int n,m,unit;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
unit=sqrt(n);
for(int i=1;i<=n;i++)block[i]=i/unit;
sort(b+1,b+n+1);
sort(q,q+m,cmp);
N=unique(b+1,b+n+1)-b-1;
int l=1,r=0;
cake(n);
for(int i=0;i<m;i++)
{
while(l<q[i].l)del(l++);
while(l>q[i].l)add(--l);
while(r<q[i].r)add(++r);
while(r>q[i].r)del(r--);
ans[q[i].id]=res;
}
for(int i=0;i<m;i++)printf("%d\n",ans[i]);
return 0;
}
若有什么错误,欢迎指正^ _ ^ 。