E. Scuza(二分)

题目:

输入
3
4 5
1 2 1 5
1 2 4 9 10
2 2
1 1
0 1
3 1
1000000000 1000000000 1000000000
1000000000

输出
1 4 4 9 9 
0 2 
3000000000 

 思路:

        这里是,二分的题目,题目的意思是有一个 数组a 是阶梯高度,数组 b 是Tim 可以跨上阶梯的高度,问Tim对应的可跨上阶梯的总 最高的 高度是多少,也有一点贪心思想

这里我们 需要记录每个台阶相应位置的 总高度, 也就是求出 前缀和 ,之后我们还要存储好到达所对应高度坐标中的  Tim 所需要的跨越高度是多少,并记录到满足该条件后对应的前缀和下标是多少。

因为我们往后都是需要前面要满足的高度,也就是说 我们后面的要到达后面的阶梯高度,需要满足前面阶梯Tim跨越的高度。

所以我们可以得到对应的单调性质,通过二分查找最后一个大于或者等于 Tim 的跨越高度即可

这里还要注意用 long long

代码详解如下:

#include <iostream>
#include <vector>
#include <unordered_map>
#define endl '\n'
#define int long long
#define umap unordered_map
#define ___G std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
int n, m;

inline int to_Find(vector<int> &v, int &x)
{
	int l = 0, r = n - 1;
	while (l < r)
	{
		int mid = l + r + 1 >> 1;
		
		if (v[mid] <= x)
			l = mid;
		else
			r = mid - 1;
	}
	return v[l];
}

inline void solve()
{
	umap<int, int>r;		// 记录对应跨越高度的坐标

	vector<int>sum;		// 对应坐标高度前缀和

	vector<int>v;	// 实际到达该坐标所需的跨越高度
	int maxs = -1;	// maxs 为满足跨越高度的探针

	cin >> n >> m;
	for (int i = 0, x; i < n; ++i)
	{
		cin >> x;
		maxs = max(maxs, x);		// 更新探针

		// 计算前缀和
		if (!i) sum.emplace_back(x);
		else sum.emplace_back(sum.back() + x);

		// 记录对应跨越高度
		v.emplace_back(maxs);

		// 记录对应跨越高度的下标
		// 即可对应其满足的前缀和
		r[maxs] = i;
	}

	for (int i = 0, x; i < m; ++i)
	{
		cin >> x;

		// 如果连第一个台阶都不能跨越
		// 那么高度就是 0
		if (x < v[0])
		{
			cout << 0 << ' ';
			continue;
		}

		// 二分查找最后一个满足 跨越高度 是多少
		int pos = to_Find(v, x);

		// 输出满足的答案
		cout << sum[r[pos]] << ' ';
	}
	cout << endl;
}

signed main()
{
	___G;
	int _t;
	cin >> _t;
	while (_t--)
	{
		solve();
	}
	return 0;
}

最后提交:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值