P7302 [NOI1998] 免费的馅饼 题解

solve

  • 首先,们可以将题目转化为类似此题:Fire(有区别但是差不多但是不能这么解),考虑dp
  • 转移方程:dp[i]=max(dp[i],dp[j]+v[i]);
  • 此时应满足:2×(t[i]−t[j]) ≥ | p[i]−p[j] |;
  • 容易发现需要两层循环,时间复杂度为O($n2$),而**n=$105$**,超时
  • 考虑用数据结构优化
  • 对于上述满足dp条件的不等式,我们进行化简得出:
  • 当p[i]≥p[j]时,有:p[j] - 2 * t[j] ≥ p[i] - 2 * t[i];
  • 当p[i]<p[j]时,有:p[i] + 2 * t[i] ≥ p[j] + 2 * t[j];
  • 对于上述两个不等式,一个用于排序,一个用于算a[i].x

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int w,n;
int c[maxn];
int dp[maxn];
int sum[maxn];
int ans;
struct node
{
	int t,p,v,x;
}a[maxn];
bool cmp (node nd1,node nd2){return nd1.p-2*nd1.t>=nd2.p-2*nd2.t;}
int lowbit(int x){return (x&(-x));}
void add(int w,int x)
{
	while(w<=n)
	{
		c[w]=max(c[w],x);
		w+=lowbit(w);
	}
}
int query(int w)
{
	int res=0;
	while(w)
	{
		res=max(res,c[w]);
		w-=lowbit(w);
	}
	return res;
}
int main()
{
	cin >> w >> n;
	for (int i=1;i<=n;i++)
	{
		cin >> a[i].t >> a[i].p >> a[i].v;
		sum[i]=2*a[i].t+a[i].p;
	}
	sort (sum+1,sum+1+n);
	for (int i=1;i<=n;i++)
	{
		a[i].x=lower_bound(sum+1,sum+1+n,2*a[i].t+a[i].p)-sum;
	}
	sort(a+1,a+1+n,cmp);
	for (int i=1;i<=n;i++)
	{
		dp[i]=query(a[i].x)+a[i].v;
		add(a[i].x,dp[i]);
		ans = max(ans,dp[i]);
	}
	cout << ans << endl;
	return 0;
}
posted @ 2026-03-22 09:32  msjing  阅读(3)  评论(0)    收藏  举报