[bzoj2131]免费的馅饼

[bzoj2131]免费的馅饼


智障一般的操作,拆绝对值都忘了。数学没救了。

最后貌似是用的几何意义推出来的。转移的条件是 t [ i ] >= t [ j ] 并且abs ( p [ i ] - p [ j ] ) <= 2 * ( t [ i ] - t [ j ] ) 显然前面那个可以不考虑。然后你把每个状态看作一个二维平面上的点nd [ i ] = ( 2 t [ i ] , p [ i ] ) 移向不难发现 nd[ i ] 能够转移的点就是y=x,y=-x的直线平移到这个点然后划分的四个区域的左边。

我们考虑将坐标系旋转45° 并且将新的横纵坐标乘上 根号2 然后 ( x , y ) 对应的新的坐标就是  ( x - y , x + y )。然后可以转移的范围就是坐标系左下的矩阵,按x轴排序更新答案,用树状数组或者线段树维护即可

  • 代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int w,n,cnt;
struct node{
    int t,p,val,x,y;
}nd[N];
inline void remark(){
    for(int i=1;i<=n;i++)
        nd[i].x=nd[i].t-nd[i].p,nd[i].y=nd[i].t+nd[i].p;
}
bool cmpy(const node a,const node b){return a.y<b.y;}
bool cmpx(const node a,const node b){return a.x==b.x?a.y<b.y:a.x<b.x;}

int f[N];

#define lowbit(x) ((x)&(-x))
int t[N];
inline void update(int pos,int sum){
    for(;pos<=cnt;pos+=lowbit(pos))t[pos]=max(t[pos],sum);
}
inline int qry(int pos){
    int mx=0;
    for(;pos;pos-=lowbit(pos))mx=max(mx,t[pos]);
    return mx;
}

int main()
{
    scanf("%d%d",&w,&n);
    for(int i=1;i<=n;i++) {
        scanf("%d%d%d",&nd[i].t,&nd[i].p,&nd[i].val);
        nd[i].t*=2;
    }
    remark();
    sort(nd+1,nd+n+1,cmpy);
    for(int i=1;i<=n;i++){
        if(i==1||nd[i].y!=nd[i-1].y)cnt++;
        nd[i].y=cnt;
    }
    sort(nd+1,nd+n+1,cmpx);
    int ans=0;
    for(int i=1;i<=n;++i){
        f[i]=nd[i].val+qry(nd[i].y);
        update(nd[i].y,f[i]);
        ans=max(ans,f[i]);
    }
    printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/qq_35923186/article/details/83388082