前言
- 欸我是不是发过一遍
- HZ26A 在学 \(DP\) 优化,于是msjing再回来学一次
- 原题
solve
- 这个东西让求最大,看的就很像 \(DP\)(· < · 雾
- 我们搓一个转移方程,设 \(f_i\) 表示第 \(i\) 个必选的最大得分
$f_i = f_j + v_i$
$(2(t_i-t_j) \ge |p_i-p_j|)$
- 我们发现柿子很简单,但是条件很复杂,我们化简一下,绝对值很烦,我们把它干掉
$
2(t_i-t_j) \ge |p_i-p_j| =
\begin{cases}
2t_i - 2t_j \ge p_i - p_j \\
2t_i - 2t_j \ge p_j - p_i
\end{cases}$
- 我们发现从一个条件变成了两个都要成立的条件,这个柿子还是不好弄,再化简一下
\begin{cases}
2t_i - p_i \ge 2t_j - p_j \\
2t_i + p_i \ge p_j + 2t_j
\end{cases}
- 这个就很好搞了,因为 \(i\) 和 \(j\) 分开了
- 我们发现这是一个二维偏序,排序干一维然后 \(DS\) 维护一维
- \(DS\) 维护时,维护 \(\ge\) 右边的,按右边的为位置,向 \(DS\) 里加入 \(f_j\),\(DS\) 内维护最大值,查询 \(\ge\) 左边的,直接转移
- \(DS\) 选 \(BIT\),又好写又快
之前写的
#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;
}