题目大意:https://www.lydsy.com/JudgeOnline/problem.php?id=2131自己看
考虑dp
dp[i][j]为时间排序后第i个馅饼掉下在第j个位置的收益
dp[i][j]=max(dp[i][j],dp[i-1][k]+v[i]);
直接转移是n^2的,考虑优化
空间上可以只考虑排序时间后的位置,i可以去掉
然后对于那个比较RiGuai的转移条件
2*(t[i]-t[j])>=|p[i]-p[j]| 然后就可以拆一波绝对值,得到两个约束条件2t[i]+p[i]≥2t[j]+p[j]&&2t[i]−p[i]≥2t[j]−p[j]
本来这样是三维的(还有时间的限制) 但是观察一波这个约束条件,两式相加可以得到时间的约束,那么就成为了二维偏序
可以用树状数组维护前缀最大值dp转移即可
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+5;
int w,n;
struct Node {
int v,t,p;
int x1,x2;
}a[maxn];
bool cmp(const Node &x,const Node &y) {
return x.x1<y.x1;
}
int tmp[maxn],f[maxn],dp[maxn],sz;
int lowbit(int x) {
return x&(-x);
}
void modify(int pos,int val) {
for (int i=pos;i<=sz;i+=lowbit(i)) {
f[i]=max(f[i],val);
}
}
int query(int pos) {
int rt=0;
for (int i=pos;i>=1;i-=lowbit(i)) {
rt=max(rt,f[i]);
}
return rt;
}
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].x1=2*a[i].t-a[i].p;
a[i].x2=2*a[i].t+a[i].p;
tmp[i]=a[i].x2;
}
sort(tmp+1,tmp+1+n);
sz=unique(tmp+1,tmp+1+n)-tmp-1;
sort(a+1,a+1+n,cmp);
for (int i=1;i<=n;i++) {
a[i].x2=lower_bound(tmp+1,tmp+1+sz,a[i].x2)-tmp;
}
int ans=0;
for (int i=1;i<=n;i++) {
dp[i]=max(dp[i],query(a[i].x2)+a[i].v);
modify(a[i].x2,dp[i]);
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
return 0;
}