HDU6534Chika and Friendly Pairs(2019JSCPC C题)

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

2019CCPC湖南全国邀请赛(广东省赛、江苏省赛)重现赛

离散化+预处理+莫队+树状数组

输入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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值