HDU 4631 - Sad Love Story(最近点对)

题意:给出A、B、C,按照给出的公式推出每一个点,添加每一个点时,求出相应的最短距离,所有最短距离加和

因为是随机点,不可能有边界数据,所以可以爆搞

每次找(0,R-1)区间的最近点对(R为上一个最近点对里面编号最大的),然后加上R到N里面所有的距离(相乘即可)

这题搞出来的。。。应该不是什么正规解法。。。跑了19015ms。。。还是太水了

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define LL long long
const int maxn = 500050;

typedef struct Point
{
    int Id;
    int No;
    LL x,y;
    Point(LL _x=0,LL _y=0,int _Id=0):x(_x),y(_y),Id(_Id){}
    bool operator < (const Point &a) const{
        return x<a.x || (x==a.x && y<a.y);
    }
}Point;

typedef struct Pair
{
    LL dis;
    int na;
    int nb;
    bool operator < (const Pair &a) const{
        return dis<a.dis ;
    }
} Pair;
int n;

Point P[maxn];
Point p[maxn],py[maxn];

int cmpy(Point a, Point b)
{
    return a.y < b.y;
}

Pair dis(Point a, Point b)
{
    Pair p;
    p.dis=(a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y);
    p.na=a.No;
    p.nb=b.No;
    return p;
}

Pair closest( int l, int r )
{
    if( l+1 == r )
        return dis( p[l], p[r]) ;
    if( l+2 == r )
        return min( dis(p[l],p[l+1]), min( dis(p[l+1],p[r]), dis(p[l],p[r]) ) ) ;
    int mid = (l+r)/2 ;
    Pair pr = min( closest(l,mid), closest(mid+1,r) ) ;
    int i, j, cnt=0 ;
    for( i=l; i<=r; i++ ){
        if( p[i].x >= p[mid].x-pr.dis && p[i].x <= p[mid].x+pr.dis ){
            py[cnt++] = p[i] ;
        }
    }
    sort( py, py+cnt, cmpy ) ;
    for( i=0; i<cnt; i++ ){
        for( j=i+1; j<cnt && (py[j].y-py[i].y)*(py[j].y-py[i].y)<pr.dis; j++ ){
            // py数组中的点是按照y坐标升序的
            pr = min( pr, dis(py[i],py[j]) ) ;
        }
    }
    return pr ;
}

int main()
{
    int T,n;
    LL ax,ay,bx,by,cx,cy;

    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&ax,&bx,&cx,&ay,&by,&cy);
        P[0]=Point(0,0,0);
        for(int i=1;i<=n;i++)
        {
            LL x = (P[i-1].x*ax + bx)%cx;
            LL y = (P[i-1].y*ay + by)%cy;
            P[i] = Point(x,y,i);
        }
        int end=n;
        LL ans=0;
        while(end>1)
        {
            for(int i = 0;i < end;i++)
                p[i] = P[i+1];
            sort(p, p+end);
            for(int i = 0;i < end;i++)
                p[i].No = i;
            Pair pr = closest(0,end-1);
            int Max = max(p[pr.na].Id,p[pr.nb].Id);
            ans += (end-Max+1)*dis(p[pr.na],p[pr.nb]).dis;
            end = Max-1;
        }
        printf("%I64d\n",ans);

    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值