未了(endless)(【CCF】NOI Online 能力测试2 入门组第一题 )

时间限制: 1.0 秒

空间限制: 256 MB

题目描述

由于触犯天神,Sisyphus 将要接受惩罚。

宙斯命 Sisyphus 推一块巨石上长度为 L的山坡。Sisyphus 匀速向上推的速度为每年 v 的长度(由于是匀速,故经过1/2年将能向上推 1/2的长度)。然而,宙斯并不希望 Sisyphus 太快到达山顶。宙斯可以施展 n 个魔法,若宙斯施展第 i个魔法(1≤i≤n),则当 Sisyphus 第一次到达位置 a i时,他将会同巨石一起滚落下山底,并从头推起。(滚落的时间忽略不计,即可看作第一次到达位置 ai后 Sisyphus 立即从山底重新出发)

例如宙斯施用了 ai =3 与 ai=5 的两个魔法。Sisyphus 的速度 v = 1,山坡的长度 L = 6,则他推石上山过程如下:

1.用 3 年走到位置 3。
2.受 ai=3 的魔法影响,回到了山底出发。
3.再用 3 年走到位置 3,然而因为是第二次到达,ai=3 的魔法不起作用。
4.用 2 年走到位置 5。
5.受 ai=5 的魔法影响,回到了山底出发。
6.用 66 年从山底走到了山顶。花费的总时间为 1414 年。

现在,宙斯有 q 个询问。对于第 i 个询问 ti,宙斯想知道,他最少需要施展多少个魔法才能使 Sisyphus 到达山顶所用的年数大于 ti 。

输入格式

第一行三个整数 n, L,v 分别表示魔法的种类数,山坡的长度,Sisyphus 的速度。

第二行 n 个整数。第 i 个整数 ai表示第 i 个魔法作用的位置。(1≤i≤n)

第三行一个整数 q 表示宙斯的询问个数。

接下来 q 行每行一个整数,第 i 行的整数 ti表示宙斯的第 ii 个询问。(1≤i≤q)

输出格式

输出 q 行,每行恰好一个整数,第 i 行的整数对应第 i 个询问的答案。(1≤i≤q)

如果宙斯无论如何都不能使 Sisyphus 使用的年数大于 ti,请输出 -1。

样例1输入

3 6 3
3 5 1
4
1
3
4
5

样例1输出

0
1
2
-1

在这里插入图片描述

正解一:

思路1:

1.首先可以发现的是高度越高耗费的时间越多,那么我们优先使用a[i]​高的魔法可以耗费更多的时间。所以就先对ai 排序。
2.数组tm[0]代表不是魔法的时间,此后tm[i]代表施i次魔法的最大时间
3.再用与tm[i]比较询问ti比较
4.最后用普通的搜索会得80分,AC的话必须用二分搜索(传送门:二分搜索)

AC的C++代码如下

#include<iostream>
#include<algorithm>
using namespace std;
int n,l,v,q,a[200010],t[200010];
double tm[200010];
int main()
{
	cin>>n>>l>>v;
	for(int i=1;i<=n;i++)
		cin>>a[i];	
	sort(a+1,a+n+1);//从小到大排序 
	tm[0]=1.0*l/v;//不受阻碍爬到山顶时间 
	for(int i=1;i<=n;i++)
		tm[i]=1.0*a[n-i+1]/v+tm[i-1];//从最大开始加 	
	cin>>q;//宙斯的询问个数	
	for(int i=0;i<q;i++)
		cin>>t[i];		
	for(int i=0;i<q;i++)//每一次询问 	
	{
		int j;
		int num=upper_bound(tm,tm+n+1,t[i])-tm;//二分搜索
		if(num==n+1)//达不到目的
			cout<<-1<<endl;
        else 
			cout<<num<<endl;
	}
	return 0;
 } 

正解二:

#include<iostream>
#include<algorithm>
using namespace std;
long long n,l,v,q,t,a[200010],sum[200010];
int main()
{
	cin>>n>>l>>v;
	for(long long i=0;i<n;i++)
		cin>>a[i];
	sum[0]=l;
	sort(a,a+n);
	reverse(a,a+n);//使从大到小排列 
	for(long long i=0;i<n;i++)
		sum[i+1]=sum[i]+a[i];
	cin>>q;
	for(long long i=0;i<q;i++)
	{
		cin>>t;//每一次询问 
		long long s=1ll*t*v;
		long long ans=upper_bound(sum,sum+n+1,s)-sum;//二分查找 
		if(ans==n+1)
			cout<<"-1"<<endl;
		else 
			cout<<ans<<endl;
	}	
	return 0;
 } 
NOI Online能力测试视频版,让我们看看出题人们怎么说!
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值