bzoj2131: 免费的馅饼

http://www.lydsy.com/JudgeOnline/problem.php?id=2131
蒟蒻不多言
直接转载:
http://blog.csdn.net/xym_csdn/article/details/51226599

转移的条件是ti>tj且|pi−pj|<=2∗(ti−tj)
这个条件等价于pi−pj<=2∗(ti−tj)且pj−pi<=2∗(ti−tj)
(推出这一步是关键)
移一下就是
2ti+pi>=2tj+pj和2ti−pi>=2tj−pj
然后就是说构成一个(2*t+p,2*t-p)的坐标系
然后维护左下角点的最大值就可以了

简单的讲讲啊,这个坐标系是什么意思呢?
就是我们对于一个i;
我们要找f[j]最大的;
j的范围就是
2ti+pi>=2tj+pj和2ti−pi>=2tj−pj
这个就是一个坐标系啊

#include<bits/stdc++.h>
#define Ll long long
using namespace std;
const int N=1e5+5;
struct cs{int v,y,x;}a[N];
int f[N],Y[N];
int n,m,ans,t,p;
bool cmp(cs a,cs b){return a.x<b.x;}//数据萎,直接按x排即可 
int er(int k){
    int l=1,r=n,mid,ans;
    while(r>=l){
        mid=l+r>>1;
        if(Y[mid]<=k)ans=mid,l=mid+1;else r=mid-1;
    }return ans;
}
void add(int x,int y){for(;x<=n;x+=x&-x)f[x]=max(f[x],y);}
int find(int x){
    int ans=0;
    for(;x;x-=x&-x)ans=max(ans,f[x]);
    return ans;
}
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&t,&p,&a[i].v);
        a[i].x=2*t+p;
        a[i].y=2*t-p;
        Y[i]=a[i].y;
    }
    sort(a+1,a+n+1,cmp);
    sort(Y+1,Y+n+1);
    for(int i=1;i<=n;i++)a[i].y=er(a[i].y);
    for(int i=1;i<=n;i++){
        m=find(a[i].y)+a[i].v;
        ans=max(ans,m);
        add(a[i].y,m);
    }
    printf("%d",ans);
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值