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;
}
posted @ 2021-05-06 14:16  棉被sunlie  阅读(71)  评论(0)    收藏  举报