【洛谷】P7302 [NOI1998] 免费的馅饼(数据结构优化dp)

原题链接

题意

SERKOI 最新推出了一种叫做“免费馅饼”的游戏:游戏在一个舞台上进行。舞台的宽度为 w 格(从左到右依次用 1w 编号),游戏者占一格。开始时游戏者可以站在舞台的任意位置,手里拿着一个托盘。

游戏开始后,从舞台天幕顶端的格子中不断出现馅饼并垂直下落。游戏者左右移动去接馅饼。游戏者每秒可以向左或向右移动一格或两格,也可以站在原地不动。

当馅饼在某一时刻恰好到达游戏者所在的格子中,游戏者就收集到了这块馅饼。当馅饼落在一个游戏者不在的格子里时该馅饼就消失。

写一个程序,帮助我们的游戏者收集馅饼,使得所收集馅饼的分数之和最大。

数据范围

1w1081n1051ti1081piw1vi1000

思路

题目中给的舞台宽度很大,但是总的馅饼数很少。考虑按照馅饼进行 dp。

f[i] 表示捡起第 i 个馅饼时获得的最大分数。根据题意,易得状态转移方程:

f[i]=min(f[j]+v[i]),其中 ij 满足 |p[i]p[j]|2×(t[i]t[j])

朴素的转移时间复杂度为 O(n2) 。由于不等式中带了绝对值,不方便进行优化, 不妨先去掉绝对值,得到:

{p[i]+2×t[i]p[j]+2×t[j],(p[i]p[j])0p[i]2×t[i]p[j]2×t[j],(p[i]p[j])<0

显然可以通过排序的方式使转移时其中一个不等式恒成立,我们不妨按照 p[i]2×t[i] 从大到小排序。那么此时因为无法判断 p[i]p[j] 大小关系,转移时仍需满足另一个不等式(因为满足最原始的不等式的决策点一定满足另一个不等式)。

注意到满足另一个不等式的是一个区间内的决策点,那么就可以先将 p[i]+2×t[i] 离散化,用树状数组维护区间最大值。时间复杂度为 O(nlogn)

code:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int w,n,num[N],tot,c[N];
struct node{int t,p,l,r,v;bool operator <(const node &tmp)const{return l>tmp.l;}}a[N];
int lowbit(int x){return x&-x;}
void update(int x,int k){while(x<=tot){c[x]=max(c[x],k);x+=lowbit(x);}}
int query(int x){int res=0;while(x){res=max(res,c[x]);x-=lowbit(x);}return res;}
int main()
{
	scanf("%d%d",&w,&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d",&a[i].t,&a[i].p,&a[i].v);
		a[i].l=a[i].p-2*a[i].t;a[i].r=a[i].p+2*a[i].t;num[i]=a[i].r;
	}
	sort(a+1,a+n+1);sort(num+1,num+n+1);tot=unique(num+1,num+n+1)-num-1;
	for(int i=1;i<=n;i++) a[i].r=lower_bound(num+1,num+tot+1,a[i].r)-num;
	for(int i=1;i<=n;i++) update(a[i].r,query(a[i].r)+a[i].v);
	printf("%d\n",query(tot));
	return 0;
}
posted @   曙诚  阅读(102)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示