【二分】 [NOI Online #2 入门组]未了
由于触犯天神, 将要接受惩罚。
宙斯命 推一块巨石上长度为 的山坡。 匀速向上推的速度为每年 的长度(由于是匀速,故经过 年将能向上推
的长度)。然而,宙斯并不希望太快到达山顶。宙斯可以施展 个魔法,若宙斯施展第 个魔法 () ,则当 第一次到达位置
时,他将会同巨石一起滚落下山底,并从头推起。(滚落的时间忽略不计,即可看作第一次到达位置 后 立即从山底重新出发)
例如宙斯施用了 和
=5 的两个魔法。 的速度 ,山坡的长度 ,则他推石上山过程如下:
用 年走到位置 。
受 的魔法影响,回到了山底出发。
再用 年走到位置 ,然而因为是第二次到达, 的魔法不起作用。
用 年走到位置 。
受 的魔法影响,回到了山底出发。
用 年从山底走到了山顶。花费的总时间为 年。
现在,宙斯有 个询问。对于第 个询问 ,宙斯想知道,他最少需要施展多少个魔法才能使 到达山顶所用的年数大于
第一行三个整数 分别表示魔法的种类数,山坡的长度, 的速度。
第二行 个整数。第 个整数 , 表示第 个魔法作用的位置。
第三行一个整数 表示宙斯的询问个数。
接下来 行每行一个整数,第 行的整数 , 表示宙斯的第 个询问。
输出 行,每行恰好一个整数,第 行的整数对应第 个询问的答案。
如果宙斯无论如何都不能使 使用的年数大于 ,请输出
3 6 3
3 5 1
4
1
3
4
5
0
1
2
-1
不使用任何魔法, 需要 年走上山顶。
使用魔法 , 需要 年走上山顶。
用时 年走到魔法 的位置并滚落下山
再用时 年走到山顶
使用魔法 , 需要 年走上山顶。
宙斯不能使 用大于 年的时间走上山顶。
很容易想到,肯定是越往后的魔法越优,因此将魔法倒序
然后求出前缀和,很容易想到一个个比较,但是这样会炸掉
因此我们要使用二分
求出第一个比读入的时间大的位置(即为答案)
还有一些特殊情况需要特判一下
记得用
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
double l, v, a[200005], s[200005];
long long n;
bool cmp(double i, double j)
{return i > j;}//降序排序
int main()
{
scanf("%lld%lf%lf", &n, &l, &v);
s[0] = l / v;
for (int i = 1; i <= n; ++i)
scanf("%lf", &a[i]);
sort(a + 1, a + n + 1, cmp);
for (int i = 1; i <= n; ++i)
s[i] = s[i - 1] + double(a[i]) / v;//求前缀和
int q;
scanf("%d", &q);
while(q--)
{
int x;
scanf("%d", &x);
if (x > s[n]) printf("-1\n");
else {
int l = 0, r = n, ans = 0;
while (l <= r)
{
int mid = (l + r) / 2;
if (s[mid] > x) r = mid - 1, ans = mid;
else l = mid + 1;
}//二分模板
printf("%d\n", ans);
}
}
return 0;
}
下一篇: php生成唯一id方法