Chika and Friendly Pairs
- 时间:1000ms
- 内存:524288K
题意:有一个大小为m的序列a,对于任意两个元素ai和aj,如果他们的差的绝对值小于等于k,我们定义其为“友好对”。现在给出n个询问[L,R],问在区间[L,R]之间有多少个“友好对”。
分析:
首先这个题只涉及区间询问,没有涉及区间修改,可以考虑用莫队进行区间暴力。
假设已知一个区间内的答案为s,那么新加入一个元素x时,可以看在原有区间中处在[x-k,x+k]之间的元素有多少个,更新s,删除一个元素时类似。而查询区间元素可以用树状数组维护,记录某个值的数的个数。
由于数的取值很大,需要进行离散化处理,缩小值域。
注意因为考虑到x±k的值,离散化时要将x,x+k,x-k均加入到离散化的数组中去。
AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
#define lowbit(x) x&(-x)
typedef long long ll;
const int maxn = 27007;
int a[maxn],X[maxn*3];
ll c[maxn*4],ans[maxn],s=0;
int bloc;
int m,n,k,xcnt=0;
struct Node
{
int key,l,r;
}mapp[maxn];
struct Query
{
int l,r,id,bl;
Query(){}
Query(int l,int r,int id):l(l),r(r),id(id){bl=(l-1)/bloc+1;}
bool operator<(const Query &rsh)
{
if(bl==rsh.bl) return r < rsh.r;
return bl < rsh.bl;
}
}queries[maxn];
ll sum(int endd)
{
ll ssum = 0;
while(endd>0)
{
ssum+=c[endd];
endd-=lowbit(endd);
}
return ssum;
}
int binX(int key,int n)
{
int pos = lower_bound(X,X+n,key)-X;
return pos == n ? -1:pos;
}
void update(int pos,int delta)
{
while(pos<=xcnt)
{
c[pos]+=delta;
pos+=lowbit(pos);
}
}
void insert(int pos)
{
s+=sum(mapp[pos].r)-sum(mapp[pos].l-1);
update(mapp[pos].key,1);
}
void erase(int pos)
{
update(mapp[pos].key,-1);
s-=sum(mapp[pos].r)-sum(mapp[pos].l-1);
}
void solve()
{
int L=1,R=0;
s=0;
for(int i = 1; i <= m; ++i)
{
Query &qi = queries[i];
while(R<qi.r) insert(++R);
while(L>qi.l) insert(--L);
while(R>qi.r) erase(R--);
while(L<qi.l) erase(L++);
ans[qi.id]=s;
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
bloc = sqrt(n+0.5);
for(int i = 1; i <= n; ++i)
{
scanf("%d",&a[i]);
X[xcnt++]=a[i];
X[xcnt++]=a[i]-k;
X[xcnt++]=a[i]+k;
}
for(int i = 1; i <= m; ++i)
{
int tl,tr;
scanf("%d%d",&tl,&tr);
queries[i]=Query(tl,tr,i);
}
sort(X,X+xcnt);
xcnt = unique(X,X+xcnt)-X;
for(int i = 1; i <= n; ++i)
{
mapp[i].key=binX(a[i],xcnt);
mapp[i].l=binX(a[i]-k,xcnt);
mapp[i].r=binX(a[i]+k,xcnt);
}
sort(queries+1,queries+1+m);
solve();
for(int i = 1; i <= m; ++i)
printf("%lld\n",ans[i]);
return 0;
}