NKOJ 4745 选点

NKOJ 4745 选点

暴力

思路

  1. 暴力枚举第一个、第二个和第三个点判断是否满足要求。
  2. 暴力枚举第一个点和第三个点,判断是否满足要求。
  3. 枚举第一个点,将其坐标 \(+d\) 设为 \(x\) ,用循环找最后一个小于等于 \(x\) 的数。

正解

暴力3是最接近正解的方法,实际上找的时候不用循环,因为数组有序,直接用二分。

思路:二分+计数

实现方法

  • 对于每一个点,用二分查找最后一个小于等于 \(\text{点坐标}+d\) 的点坐标 \(p\),找到后,中间所有的点都可以选。
  • 能选的点共有 \(len=i-p+1\) 个,其中 \(i\) 是当前的点坐标。而选的方案一共有 \(\frac{len \times (len-1)}{2}\) 种,因为每一个点都可以选,选完后能和剩下 \(n-1\) 个点匹配,但要除掉重复的。

代码

#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
int n,d,ans=0;
int arr[100005];
signed main(){
	scanf("%lld%lld",&n,&d);
	for(int i=1;i<=n;i++) scanf("%lld",&arr[i]);
	for(int i=1;i<=n;i++){
		int p=lower_bound(arr+1,arr+1+n,arr[i]+d)-arr;
		if(arr[p]>arr[i]+d||p>n) p--;
		int len=i-p+1;
		ans+=(len-1)*len/2;
	}
	printf("%lld",ans);

	return 0;
}
posted @ 2025-04-13 15:48  hsr_ray  阅读(6)  评论(0)    收藏  举报