【bzoj2131】免费的馅饼 dp+树状数组
题解:
昨天好像做了个几乎一模一样的题目
按照ti排序 |p[i]-p[j]|<=2*(t[i]-t[j])
然后去绝对值变为三维偏序
发现后两个式子可以推出ti<tj
所以就变成二维偏序 按照一个排序套线段树就可以了
代码非常好写
代码:
#include <bits/stdc++.h> using namespace std; #define rint register ll #define IL inline #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) #define ll long long #define mid ((h+t)>>1) const ll N=2e5; const ll N2=6e6; const ll INF=1e9; struct re{ ll a,b,p,v,t; }a[N]; bool cmp(re x,re y) { return x.a<y.a; } ll cnt; struct sgt{ ll ls[N2],rs[N2],data[N2]; void insert(ll &x,ll h,ll t,ll pos,ll k) { if (!x) x=++cnt; data[x]=max(data[x],k); if (h==t) return; if (pos<=mid) insert(ls[x],h,mid,pos,k); else insert(rs[x],mid+1,t,pos,k); } ll find(ll x,ll h,ll t,ll h1,ll t1) { if (h1<=h&&t<=t1) return(data[x]); ll ans=0; if (h1<=mid) ans=max(ans,find(ls[x],h,mid,h1,t1)); if (mid<t1) ans=max(ans,find(rs[x],mid+1,t,h1,t1)); return(ans); } }S; int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); ll w,n; cin>>w>>n; rep(i,1,n) { cin>>a[i].t>>a[i].p>>a[i].v; a[i].a=2*a[i].t-a[i].p; a[i].b=2*a[i].t+a[i].p; } sort(a+1,a+n+1,cmp); ll ans=0; ll rt=0; rep(i,1,n) { ll tmp=S.find(1,1,INF,1,a[i].b)+a[i].v; ans=max(ans,tmp); S.insert(rt,1,INF,a[i].b,tmp); } cout<<ans<<endl; return 0; }