2019CCPC湖南全国邀请赛 C - Chika and Friendly Pairs
给你一个长度为n的序列,有m次查询操作,每次查询[L,R]区间的友好对的个数。
友好对的定义:满足i<j,且|ai-aj|<=K。
考虑每添加一个元素,计算该元素范围内[x-k,x+k]有多少个数(对树状数组来一发询问即可 query(r) - query(l-1) ),加上该贡献;
离散所给数组,将a[i]-k和a[i]+k也加入,也离散;
用树状数组以及莫队解决
#include <bits/stdc++.h>
using namespace std;
#define MS 27009
#define ls rt<<1
#define rs rt<<1|1
#define LL long long
#define ll long long
#define MAXN 20000000000
#define mod 1000000007
LL n,m,k;
LL p[MS*3];
LL a[MS];
LL b[MS*3],tb;
struct node{
int l,r,id;
}ask[MS];
LL unit;
LL ac[MS];
struct nod{
int pos,posl,posr;
}apos[MS];
LL lowbit(LL x){
return x&(-x);
}
bool cmp(node t1,node t2){
if(t1.l/unit == t2.l/unit) return t1.r < t2.r;
return t1.l/unit < t2.l/unit;
}
int getposb(LL x){
if(x < 0) return 0;
return lower_bound(b+1,b+tb+1,x)-b;
}
void add(int pos,LL val){
for(;pos<=tb;pos+=lowbit(pos)) p[pos] += val;
}
LL getnum(int pos){
LL ansl = 0;
LL ansr = 0;
int posl = apos[pos].posl-1;
int posr = apos[pos].posr;
for(;posl>0;posl-=lowbit(posl)) ansl += p[posl];
for(;posr>0;posr-=lowbit(posr)) ansr += p[posr];
return ansr - ansl - 1ll;
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m >> k;
for(int i=1;i<=n;i++){
cin >> a[i];
b[++tb] = a[i];
if(a[i]-k>0) b[++tb] = a[i]-k;
b[++tb] = a[i]+k;
}
sort(b+1,b+tb+1);
LL h = tb;
tb = 1;
for(int i=2;i<=h;i++){
if(b[i] != b[i-1]) b[++tb] = b[i];
}
for(int i=1;i<=n;i++){
int pos = getposb(a[i]);
int posl = getposb(a[i]-k);
int posr = getposb(a[i]+k);
apos[i] = {pos,posl,posr};
}
for(int i=1;i<=m;i++){
int l,r;
cin >> l >> r;
ask[i] = {l,r,i};
}
unit = sqrt(n);
sort(ask+1,ask+m+1,cmp);
int L = 1,R = 0;
LL ans = 0;
for(int i=1;i<=m;i++){
int l = ask[i].l;
int r = ask[i].r;
while(L < l){
ans -= getnum(L);
add(apos[L].pos,-1);
L++;
}
while(L > l){
L--;
add(apos[L].pos,1);
ans += getnum(L);
}
while(R < r){
R++;
add(apos[R].pos,1);
ans += getnum(R);
}
while(R > r){
ans -= getnum(R);
add(apos[R].pos,-1);
R--;
}
ac[ask[i].id] = ans;
}
for(int i=1;i<=m;i++){
cout << ac[i] << "\n";
}
return 0;
}