BZOJ2131: 免费的馅饼

Description

Input

第一行是用空格隔开的二个正整数,分别给出了舞台的宽度W(1到10^8之间)和馅饼的个数n(1到10^5)。  接下来n行,每一行给出了一块馅饼的信息。由三个正整数组成,分别表示了每个馅饼落到舞台上的时刻t[i](1到10^8秒),掉到舞台上的格子的编号p[i](1和w之间),以及分值v[i](1到1000之间)。游戏开始时刻为0。输入文件中同一行相邻两项之间用一个空格隔开。输入数据中可能存在两个馅饼的t[i]和p[i]都一样。

Output

一个数,表示游戏者获得的最大总得分。

Sample Input

3 4
1 2 3
5 2 3
6 3 4
1 1 5

Sample Output

12
【数据规模】
对于100%的数据,1<=w,t[i]<=10^8,1<=n<=100000。
 
我还是太年轻了被AKC艹爆
本来想DP的,看到N<=100000放弃了,结果不会做。。。
其实就是DP(我个愣头青
f[i]表示接了第i个馅饼的最大值,方程很容易搞出来,但是有个限制条件:
f[i]=max(  f[j]  +  v[i]  )               | pi-pj | /2<=ti-tj
然后化一波柿子:
|pi-pj|<=2*ti-2*tj     ====      pi-pj<=2*ti-2*tj && pj-pi<=2*ti-2*tj  ==== 2*ti-pi>=2*tj-pj && 2*ti+pi>=2*tj+pj
然后就变成二维偏序问题了。。排个序树状数组维护一下就OK
//MT_LI
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,w;
int lowbit(int x){return x&-x;}
ll cc[210000];
void change(int x,ll d){while(x<=n+1){cc[x]=max(cc[x],d);x+=lowbit(x);}}
ll getmax(int x){ll ans=0;while(x){ans=max(ans,cc[x]);x-=lowbit(x);}return ans;}
struct node{
    int x,y;ll v;
}a[210000];
int LS[210000];
bool cmp(node a,node b)
{
    if(a.x!=b.x)return a.x<b.x;
    return a.y<b.y;
}
int main()
{
    scanf("%d%d",&w,&n);
    for(int i=1;i<=n;i++)
    {
        int t,p;
        scanf("%d%d%lld",&t,&p,&a[i].v);
        a[i].x=2*t+p;a[i].y=2*t-p;
        LS[i]=a[i].y;
    }
    sort(a+1,a+1+n,cmp);
    sort(LS+1,LS+1+n);
    for(int i=1;i<=n;i++)
    {
        ll ans=0ll;int pos=lower_bound(LS+1,LS+n+1,a[i].y)-LS;
        ans=getmax(pos)+a[i].v;
        change(pos,ans);
    }
    printf("%lld\n",getmax(n+1));
    return 0;
} 

 

 
posted @ 2018-10-10 20:21  MT_LI  阅读(395)  评论(0编辑  收藏  举报