bzoj1560: [JSOI2009]火星藏宝图
考虑到一个性质,A到B的距离一定不小于A到C再到B的距离,因为能够到达这三个点不可能构成锐角三角形
对于当前点的更新只需要找那些无法经过其它点再到当前点的点,相当于是一个y坐标单调减的上凸包,随便维护下
卡常让我迷失了心智
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; const int inf=(1<<30); inline int sqr(int x){return x*x;} inline int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} return x*f; } struct point{int x,y,d;}p[210000]; inline bool cmp(point p1,point p2){return p1.x==p2.x?p1.y<p2.y:p1.x<p2.x;} inline int dis(int i,int j){return sqr(p[i].x-p[j].x)+sqr(p[i].y-p[j].y);} int up[2100][2100]; int f[210000]; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int n,m,k,i,j; n=read(),m=read(); for(i=1;i<=n;i++) p[i].x=read(),p[i].y=read(),p[i].d=read(); sort(p+1,p+n+1,cmp); for(i=1;i<=n;i++)up[p[i].x][p[i].y]=i; for(j=m;j>=1;j--) for(i=1;i<=m;i++) if(!up[i][j])up[i][j]=up[i][j+1]; f[1]=p[1].d; p[0].y=inf; for(i=2;i<=n;i++) { k=1; f[i]=-inf; if( !(up[p[i].x][k]==i||p[up[p[i].x][k]].y>p[i].y) ) { while(k<p[i].y&& !(up[p[i].x][k+1]==i||p[up[p[i].x][k+1]].y>p[i].y) )k=p[up[p[i].x][k+1]].y; if(f[up[p[i].x][k]]!=-inf) f[i]=max(f[i],f[up[p[i].x][k]]-dis(i,up[p[i].x][k])+p[i].d); } for(j=p[i].x-1;j>=1;j--)//纵 { if( !(p[up[j][k]].y>p[i].y) ) { while(k<p[i].y&& p[up[j][k+1]].y<=p[i].y )k=p[up[j][k+1]].y; if(f[up[j][k]]!=-inf) f[i]=max(f[i],f[up[j][k]]-dis(i,up[j][k])+p[i].d); k++; } } } printf("%d\n",f[n]); return 0; }
pain and happy in the cruel world.