首先看到每个物品(馅饼)有三个属性(时间$t$,位置$p$,价值$v$),容易想到以物品为阶段来$dp$
令$f[i]$表示到第$i$个物品的最大收益
有
$$f[i] = maxleft { f[j]
ight }+v[i],2*(t[i] - t[j])geq left | p[i] - p[j]
ight |$$
将$t[i]*2$,然后将限制条件化简可得
$$left{egin{matrix}
t[j]-p[j]leq t[i]-p[i]\
t[j]+p[j]leq t[i]+p[i]
end{matrix}
ight.$$
令$t[i]-p[i] = x,t[i]+p[i] = y$
就成了模板的二维偏序,第一维排序,第二维树状数组维护即可(与P3431 [POI2005]AUT-The Bus一模一样)
代码如下
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 #include <queue> 6 #define ll long long 7 using namespace std; 8 9 template <typename T> void in(T &x) { 10 x = 0; T f = 1; char ch = getchar(); 11 while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();} 12 while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();} 13 x *= f; 14 } 15 16 template <typename T> void out(T x) { 17 if(x < 0) x = -x , putchar('-'); 18 if(x > 9) out(x/10); 19 putchar(x%10 + 48); 20 } 21 //------------------------------------------------------- 22 23 const int N = 1e5+7; 24 25 int n,m; 26 ll b[N],ans; 27 28 struct obj { 29 ll x,y;int v; 30 bool operator < (const obj &sed) const { 31 return x == sed.x ? y < sed.y : x < sed.x; 32 } 33 }p[N]; 34 35 struct Map { 36 ll pos,v; 37 bool operator < (const Map &sed) const { 38 return v == sed.v ? pos < sed.pos : v < sed.v; 39 } 40 }a[N]; 41 42 void ls_y() { 43 sort(a+1,a+n+1); 44 int _id = 0,i; 45 for(i = 1;i <= n; ++i) { 46 if(a[i].v != a[i-1].v) ++_id; 47 p[a[i].pos].y = _id; 48 } 49 } 50 51 ll Q(int pos) { 52 ll res = 0; 53 for(int i = pos;i;i -= i&-i) res = max(res,b[i]); 54 return res; 55 } 56 57 void A(int pos,ll k) { 58 for(int i = pos;i <= n;i += i&-i) b[i] = max(b[i],k); 59 } 60 61 int main() { 62 //freopen("0.in","r",stdin); 63 int i; ll t,pos; in(m); in(n); 64 for(i = 1;i <= n; ++i) { 65 in(t); in(pos); in(p[i].v); 66 p[i].x = (t<<1) - pos; p[i].y = (t<<1) + pos; 67 a[i].pos = i,a[i].v = p[i].y; 68 } 69 ls_y(); 70 sort(p+1,p+n+1); 71 for(i = 1;i <= n; ++i) { 72 ll _f = Q(p[i].y) + p[i].v; 73 ans = max(ans,_f); 74 A(p[i].y,_f); 75 } 76 out(ans); 77 return 0; 78 }