其他分享
首页 > 其他分享> > 斑羚飞渡

斑羚飞渡

作者:互联网

原题题址

题目描述

题目背景

两个人之间只能有一个活着 ,这必然是我和你的战争——Harry Potter
题目描述

水宝宝在看完《斑羚飞渡》这本书后,突发奇想,想到了一个有趣的问题
现在峡谷的这边有n只斑羚,每只斑羚跳跃的最远距离为x[i],斑羚在别人的背上起跳的最远距离为y[i],峡谷的两岸的距离为s,问在最好情况下,有几只斑羚可以用别人的背当跳板跳到对岸,但由于斑羚的先天原因(主要是太肥),只能把别人当跳板一次

输入描述:

输入格式:
第一行n,s 接下来n行,每行2个整数代表x[i],y[i]

输出描述:

输出格式:
一行一个整数,表示有几只斑羚可以用别人的背当跳板跳到对岸

示例1

输入

5 10
6 8
2 100
7 3
1 10
2 5

输出

2

说明

第一组是第三只斑羚跳6的距离,第一只斑羚跳6的距离后从第三只的背上起跳,再跳8的距离后到达对岸

第二组是第五只跳2的距离,第二只跳2的距离后从第五只的背上起跳,跳100的距离到达对岸(假设对岸无限长,不可能跳出对岸)

备注:

对于100%的数据,n<=1000000;

对于所有数据,s<=1000000000; x[i],y[i]<=s; 不保证x[i]<y[i]

该题要想清楚了,就set什么的t都不要。

首先能自己跳过去的斑羚就在输入时计数,而且不存入。

(1)在是经别人帮助能跳可能过去的(x+y>=s)只需要读入y
别人帮忙也跳不过去的只需要读入x。
下面给出(1)的证明:

1)别人帮忙也不行的肯定只能帮别人了,它的y我们不关注,只需要关注,它的x1x_{1}x1​和需要他帮助的y2y_{2}y2​,只要它能满足x1x_{1}x1​+y2y_{2}y2​>=s,那在跳第一步的时候只需要都跳s - y2即可(被帮助的肯定能跳那么远,毕竟x2x_{2}x2​+y2y_{2}y2​>=s)
2)当不可能过去的将能帮的都帮了之后,可能还剩有人帮能过去的斑羚能过去(不止一只,一只自己过不去),他们还能过去/2\lfloor{(剩余的有机会过去的斑羚数量)/2} \rfloor⌊(剩余的有机会过去的斑羚数量)/2⌋只。

2) 证明:对于任意两只斑羚,他们的自身跳的距离x1x_{1}x1​,x2x_{2}x2​必定有,一个大于等于一个。当x1x_{1}x1​<=x2x_{2}x2​时,x2x_{2}x2​当踏板,两只同时跳x1x_{1}x1​远,第一只再踩一下第二只过去了。反之第二只就过去了。所以两两任意组合都能过去一只。所以最少过去它们的一半。所以此时与它们的x,y都无关。

上代码(set版,就代码操作比较简单,并不是上文讲的,这个没啥好讲的):

#include"iostream"
#include"set"
#include"cstdio"
#include"algorithm"
#define maxn 1000000+5
using namespace std;
typedef long long ll;
ll read(){
    ll s = 0,w = 1;
    char c = getchar();
    while(c >'9'||c <'0'){w*=-1;c = getchar();}
    while(c>='0'&&c <='9'){s = s*10 +c-'0';c=getchar();}
    return w*s;
} 
typedef struct BL{
    ll x,y;
    bool operator <(const BL a)const
    {
        if(y!=a.y)
            return y<a.y;
        return x<a.x;
    }
}BL;
BL  D[maxn];
bool b[maxn];
int main(){ 
    multiset<int> a;
    ll n,s,X,Y,cnt = 0,ans = 0,Num = 0;
    n = read();s = read();
    for(int i = 0;i < n;i++){
        X = read();Y = read();
        if(X>=s){
		ans++;
		continue;
		}
        else{
            if(X+Y>=s){
			D[cnt].x = X;
            D[cnt].y = max((ll)1,s - Y);
			cnt++;
            }
            else{
            a.insert(X);	
			} 	
        }
    } 
	sort(D,D+cnt);
	multiset<int> ::iterator it;
	for(int i = 0;i < cnt;i++){
		it = a.lower_bound(D[i].y);
		if(it!=a.end()){
			ans++;
			a.erase(it);
		}
		else{
			Num++;
		} 
	}
    ans +=Num/2;
    cout <<ans;
}

普通的没有用set是上文写的那种

include<stdio.h>
#include<algorithm>
#define int long long
using namespace std;
int y[1000005],x[1000005];//a,c 可能跳过去的,b 一定不能跳过去的
 
bool cmp(int p,int q)
{
    return p>q;//降序
}
 
signed main(){
    int n,l;
    int X,Y,j=0,k=0,ans=0;
    scanf("%lld%lld",&n,&l);
    for(int i = 0 ; i < n ; i ++ )
    {
        scanf("%lld%lld",&X,&Y);
        if(X>=l)
        ans++;
        else if(X+Y<l){
            x[k++]=X;
        }
        else{
            y[j++]=Y;
        }
    }
    sort(x,x+k);
    sort(y,y+j,cmp);
     
    int f=0;
    int i;
    for(i = 0 ; i < j && f < k ; i ++ ){
        int temp=y[i];
        while( f < k ){
            if(temp+x[f]>=l){
                ans++;
                f++;
                break;
            }
            else f++;
        }
    }
    if(i==j)
    printf("%lld",ans);
    else printf("%lld",ans+(j-i)/2);
    return 0;
}

标签:cnt,++,斑羚,int,ans,飞渡,include
来源: https://blog.csdn.net/weixin_43751631/article/details/92207388