【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;
}

 

posted @ 2018-09-17 22:22  尹吴潇  阅读(184)  评论(0编辑  收藏  举报