zoukankan      html  css  js  c++  java
  • HDU 5721Palace

    Palace

     
     Accepts: 28
     
     Submissions: 307
     Time Limit: 8000/4000 MS (Java/Others)
     
     Memory Limit: 262144/262144 K (Java/Others)
    问题描述
    为了寻找失去的爱人Cupid,Psyche需要完成Venus的最后一项任务:前往冥界,收集一盒冥界皇后Prosperina的美貌。
    
    冥界有nn个神殿,可以表示为平面上的nn个整点。Psyche想要找到这nn座神殿中,最近的两座神殿之间的距离。传说那就是通往主殿的密码。
    
    但是冥界神秘莫测,在不同的时刻,这nn座神殿中的某一座会消失。
    
    Psyche想要知道,对于nn座神殿中的任意一座消失的情况,最近的两座神殿之间的距离。你只需要输出它们的和。
    
    为避免精度误差,定义两点(x_1, y_1), (x_2, y_2)(x1,y1),(x2,y2)间的距离为d = (x_1 - x_2) ^ 2 + (y_1 - y_2) ^ 2d=(x1x2)2+(y1y2)2
    输入描述
    第一行,一个整数TT (1 le T le 5)(1T5),代表数据组数。
    
    对于每组数据,第一行,一个整数nn (3 le n le 10 ^ 5)(3n105),代表神殿个数。
    
    下面nn行,每行两个整数x, yx,y (-10 ^ 5 le x,y le 10 ^ 5)(105x,y105),代表神殿的位置在(x, y)(x,y)。
    
    注意可能存在两座神殿坐落在同一位置。
    输出描述
    输出TT行,对于每组数据,输出nn座神殿中的任意一座消失的情况,最近两座神殿之间的距离的和。
    输入样例
    1
    3
    0 0
    1 1
    2 2
    输出样例
    12
    Hint
    神殿(0,0)(0,0)消失时,d = (1-2) ^ 2 + (1 - 2) ^ 2 = 2d=(12)2+(12)2=2;
    
    神殿(1,1)(1,1)消失时,d = (0-2) ^ 2 + (0 - 2) ^ 2 = 8d=(02)2+(02)2=8;
    
    神殿(2,2)(2,2)消失时,d = (0-1) ^ 2 + (0-1) ^ 2 = 2d=(01)2+(01)2=2;
    
    故答案为2 + 8 + 2 = 122+8+2=12

    解题思路:

    感觉就是很裸的平面最近点对的模板题= =题解上的说的也很明确了,只有三种情况

    一种情况是删的点不属于最近点对里面的点

    剩下两种情况各删的最近点对里面的其中一点


    代码如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define INF 1e18
    #define Min(a, b) ((a) <= (b) ? (a) : (b))
    
    typedef long long LL;
    typedef struct node{
        LL x, y;
        LL index;
    }Coord;
    
    const int maxn = 1e5 + 5;
    
    LL p1, p2, ans;
    Coord p[maxn], ppp[maxn], tmp[maxn];
    
    inline LL f(LL x){
        return (x >= 0 ? x : -x);
    }
    inline bool cmp(Coord a, Coord b){
        return a.x < b.x;
    }
    inline bool cmp2(Coord a, Coord b){
        return a.y < b.y;
    }
    inline LL Dist(Coord a, Coord b){
        return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
    }
    LL Cal_Closest(LL left, LL right, int step){
        LL d = INF;
        if(left == right){
            return d;
        }
        if(left + 1 == right){
            LL tmp2 = Dist(p[left], p[right]);
            if(step == 0){
                if(step == 0 && tmp2 < ans){
                    p1 = left;
                    p2 = right;
                    ans = tmp2;
                }
            }
            return tmp2;
        }
        
        LL mid = (left + right) >> 1;
        LL d1 = Cal_Closest(left, mid, step);
        LL d2 = Cal_Closest(mid + 1, right, step);
        d = Min(d1, d2);
        
        LL k = 0;
        for(LL i = left; i <= right; ++i){
            if(f(p[mid].x - p[i].x) <= d){
                tmp[k++] = p[i];
            }
        }
        sort(tmp, tmp + k, cmp2);
        
        for(LL i = 0; i < k; ++i){
            for(LL j = i + 1; j < k && tmp[j].y - tmp[i].y < d; ++j){
                if(d > Dist(tmp[i], tmp[j])){
                    d = Dist(tmp[i], tmp[j]);
                    if(step == 0 && d < ans){
                        p1 = tmp[i].index;
                        p2 = tmp[j].index;
                        ans = d;
                    }
                }
            }
        }
        return d;
    }
    
    int main()
    {
        LL t, n;
        scanf("%lld", &t);
        while(t--){
            scanf("%lld", &n);
            memset(p, 0, sizeof(p));
            memset(ppp, 0, sizeof(ppp));
            for(LL i = 0; i < n; ++i){
                scanf("%lld%lld", &p[i].x, &p[i].y);
            }
            
            sort(p, p + n, cmp);
            for(LL i = 0; i < n; ++i) p[i].index = i;
            for(LL i = 0; i < n; ++i) ppp[i] = p[i];
            p1 = 0; p2 = 0;
            ans = INF;
            
            ans = Cal_Closest(0, n - 1, 0);
            ans = ans * (n - 2);
            
            LL t = 0;
            for(LL i = 0; i < n; ++i){
                if(ppp[i].index == p1) continue;
                p[t++] = ppp[i];
            }
            sort(p, p + t, cmp);
            ans += Cal_Closest(0, t - 1, 1);
            
            t = 0;
            for(LL i = 0; i < n; ++i){
                if(ppp[i].index == p2) continue;
                p[t++] = ppp[i];
            }
            sort(p, p + t, cmp);
            ans += Cal_Closest(0, t - 1, 1);
            printf("%lld
    ", ans);
        }
        return 0;
    }


  • 相关阅读:
    复杂链表的复制
    [CSP-S模拟测试]:抽卡(概率DP)
    [CSP-S模拟测试]:计划(前缀和)
    [CSP-S模拟测试]:公园(BFS+剪枝)
    [CSP-S模拟测试]:长寿花(DP+组合数)
    [CSP-S模拟测试]:喝喝喝(模拟)
    [CSP-S模拟测试]:次芝麻(数学)
    [CSP-S模拟测试]:赤壁情(DP)
    [CSP-S模拟测试]:密州盛宴(贪心)
    [CSP-S模拟测试]:春思(数学)
  • 原文地址:https://www.cnblogs.com/wiklvrain/p/8179458.html
Copyright © 2011-2022 走看看