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

 

posted @ 2019-01-15 15:37  AKCqhzdy  阅读(148)  评论(0编辑  收藏  举报