Codeforces Round #153 (Div. 2) C题

博客讲述了在Codeforces Round #153 (Div. 2) C题中,如何解决关于数轴上寻找满足特定条件的三个点的问题。通过二分搜索的方法,结合组合数学,枚举每个点并计算以该点为起点的最大区间,同时注意消除重复情况。
摘要由CSDN通过智能技术生成

这几天在做CF,DIV2的题大多是YY题,不过感觉这里的题比较有技巧,比较新颖,挺好玩的。。


题意:给定一个数轴,有n个不同的点,求任取3个点使这3个点的两两距离都不超过d;

思路:二分就可以了,可以当作是组合数学来做。。

枚举每个点,然后二分找出以当前点为起点所能构成的最大区间,然后再减去与上个

点重复的那部分;

如n=5,d=3;Xi=1,2,3,4,5;则枚举1时,以1为起点所能构成的区间包含的点

为1,2,3,4;有3种情况满足条件res+=3;枚举以2为起点时,则以2为起点所能

构成区间包含的点为2,3,4,5,则res+=3;但(2,3,4)这个可能重复了要减去1,

以此类推;

//author Joy

#pragma comment(linker, "/STACK:66777216")
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cctype>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
#define LL __int64
using namespace std;
typedef struct coor
{
    int x,y;
};

int nomalDay[]={0,31,28,31,30,31,30,31,31,30,31,30,31};//平年
int leapDay[]={0,31,29,31,30,31,30,31,31,30,31,30,31};//闰年
const int ARRSIZE=100100;
const int STRSIZE=100100;
const int GRIDSIZE=510;
const int MAXINF=(2<<20);
const int MININF=(~(2<<20));

inline bool upcmp(int a,int b)
{
    return a<b;
}
inline bool downcmp(int a,int b)
{
    return a>b;
}
/*---------------分割线---------------*/
int num[ARRSIZE];

LL fac(LL n)	//谨记:当中间结果超过int的时候要用long long,因为这里WA两次,TAT。。
{
	if(n<3)
		return 0;
	return (n*(n-1)*(n-2))/6;
}

int bs(int a[], int l, int h, int v)
{
    int m;
    while ( l < h )
    {
        m = ( l + h ) >> 1;
        if (a[m] < v) l=m+1;
        else h=m;
    }
    return l;
}

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
    int n,d;
    while (cin>>n>>d)
    {
        int i,last=1;
        LL res=0;
        for (i=1;i<=n;i++)
            scanf("%d",&num[i]);
        for(i=1;i<=n;i++)
       	{
	    	int idx=bs(num,i,n,num[i]+d);
			if(num[idx]>num[i]+d)
				idx--;
			res+=fac(idx-i+1);
			res-=fac(last-i+1);
			last=idx;
       	}
        cout<<res<<endl;   
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值