[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);
}