您当前的位置: 首页 >  ar

不牌不改

暂无认证

  • 0浏览

    0关注

    422博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

1044 Shopping in Mars (25 分)

不牌不改 发布时间:2022-04-16 20:11:18 ,浏览量:0

题目

题目链接

题解

二分。

整体思路:计算累加和,枚举区间左端点,二分满足要求的区间右端点,记录左右端点。

满足的条件,找到的右端点和左端点之间的和大于等于pay。但是我们枚举每个左端点二分到区间和可能不正好是pay,所以我们将差值作为键,以vector作为值保存全部差值为key的区间信息。

产生了另一个问题,我们如何二分得到右端点?因为我们只能计算出前缀和,并不能直接计算出区间和,既然要求[l,r]区间和大于等于pay,那么我们只要要求[1,r]区间和大于pay+sum[l-1]即可,sum[i]表示前缀和。解决了!

虽然很快写出来了,但是感觉还挺有意思的,记录一下。

一开始不知道累加和如何转换到一段区间的和,想保存在sum[l][r]中,但是这样时间复杂度就又到 n 2 n^2 n2了,所以想自己手写二分来判断,后来灵光一现,可以直接进行上面的处理达到目的!

代码
#include
using namespace std;
#define PII pair 
const int N = 1e5+10;

int n, pay, x, a[N], mindiff = 0x3f3f3f3f;
map  diff; // key:表示多出来的钱数,value表示一个set,保存左右端点(其实vector也可以,因为我们插入的顺序就是按题目要求的) 

int main()
{
	cin >> n >> pay;
	for (int i = 1;i > x, a[i] = a[i-1] + x; // 计算前缀和 
	
	for (int i = 1;i  n) continue;
		int d = a[p] - sum;	// 多出来的钱 
		diff[d].insert ({i, p}); // 保存左右端点 
		mindiff = min (mindiff, d); // 最小差值 
	}
	
	for (PII item : diff[mindiff]) 
		cout             
关注
打赏
1662186765
查看更多评论
0.4745s