ybt1673 楼间跳跃

1673:楼间跳跃

时间限制: 2000 ms 内存限制: 262144 KB

【题目描述】

在一条街道上有\(n\)栋楼,第\(i\)栋有\(h_i\)层,每层都有价值为\(v_i\)的物品。

Lyra可以花费一单位时间在同一栋楼中向上或向下走一层。特别地,每栋楼里都有一个大滑梯,只能从顶楼通往一楼,所以如果Lyra在顶层,可以花费一单位时间通过滑梯到达一楼(注意只有在顶楼才可以使用滑梯)。

Lyra还可以在不同的楼之间跳跃,即花费一单位时间从当前楼移动到相邻楼的同层,如果相邻楼没有Lyra当前位置高,则会落到相邻楼的顶层。

初始时Lyra在第一栋楼的顶层,她有\(m\)单位时间可以移动,Lyra拿去物品不需要时间,且一个物品被拿一次之后就会消失。

Lyra想知道她能获得的总价值最多是多少?

【输入】

第一行两个正整数\(n,m\)

以下\(n\)行每行两个整数表示\(h_i\)\(v_i\)

提示:输入数据较大,请采用快速的读入方式。

【输出】

输出一行一个整数表示最大的总价值。

【输入样例】

3 3
2 1
1 5
3 4

【输出样例】

14

【数据规模及约定】

对于20%的数据,\(Σh_i≤20\)

对于另外10%的数据,\(v_i=1\)

对于另外30%的数据,\(Σh_i≤1000\)

对于另外20%的数据,\(n,h_i≤10^5\)

对于100%的数据,\(n,h_i≤10^6\)


这不就是钓鱼那个题的变种嘛!
注意开long long,否则会挂3个点!


#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
long long n,m;
struct node
{
	long long h,v;
	bool operator < (node b) const 
	{
		return v>b.v;
	}
}lou[maxn];
priority_queue< node > q;
long long q_cnt,q_sum;
long long sm[maxn];
long long ans,cur;
int main()
{
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;++i)
	{
		scanf("%lld%lld",&lou[i].h,&lou[i].v);
		sm[i]=sm[i-1]+lou[i].v;
	}
	for(int i=1;i<=min(m+1,n);++i)
	{
		cur=sm[i];
		if(lou[i].h>1)
		{
			q_cnt+=lou[i].h-1;
			q_sum+=1LL*(lou[i].h-1)*lou[i].v;
			q.push((node){lou[i].h-1,lou[i].v});
		}
		while(m-i+1<=q_cnt-q.top().h)
		{
			q_cnt-=q.top().h;
			q_sum-=1LL*q.top().v*q.top().h;
			q.pop();
		}
		if(q_cnt<=m-i+1)cur+=q_sum;
		else cur+=q_sum-1LL*(q_cnt-(m-i+1))*q.top().v;
		ans=max(cur,ans);
	}
	cout<<ans<<endl;
	return 0;
} 

posted on 2024-12-12 15:53  gryzy  阅读(32)  评论(0)    收藏  举报

导航