Minimum Sum(平面对近点对+分治)

Minimum Sum(分治)

题目链接

题意:

现在有 n n n 个向量, v i = ( x i , y i ) v_i = (x_i,y_i) vi​=(xi​,yi​)

  • v i 1 = ( x i , y i ) v_i^1 = (x_i, y_i) vi1​=(xi​,yi​)
  • v i 2 = ( − x i , y i ) v_i^2 = (-x_i, y_i) vi2​=(−xi​,yi​)
  • v i 3 = ( x i , − y i ) v_i^3 = (x_i,-y_i) vi3​=(xi​,−yi​)
  • v i 4 = ( − x i , − y i ) v_i^4=(-x_i,-y_i) vi4​=(−xi​,−yi​)

求 m i n { ∣ v i k 1 + v j k 2 ∣ } min\{|v_i^{k1} + v_j^{k2}|\} min{∣vik1​+vjk2​∣}

思路:

向量和 转换成 两点间的距离。最后答案只需要点对的对第二个点全部取负,即 1 1 1 <-> 4 4 4 , 2 2 2 <-> 3 3 3 。

每个点可以分成四个点,记录一下原来的序号和对应的指数,在分治比较时,相同序号的点不要比较即可。

这里分治时,当前区间的最小距离和答案的最小距离要分开更新,不然前者更新的时候有可能会覆盖掉后者更新过的答案。惨痛的经历

还有,这题要加上

freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);

M L E MLE MLE 了一晚上。。

代码:

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<map>
#include<set>
#include<cstring>
#include<string>
#include<algorithm>
#define fi first
#define se second
//#include<stdlib.h>
//#include <time.h>
//srand((unsigned)time(NULL));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
using namespace std;
const int N = 4e5 + 10;
int n;
int tp[N];
int dx[5] = {0, 1, -1, 1, -1};
int dy[5] = {0, 1, 1, -1, -1};
struct Point{
    int x, y;
    int id, k;
    Point() {}
    Point(int _x, int _y) {
        x = _x; y = _y;
    }
}p[N];
bool cmp1(const Point& a, const Point& b) {
    if (a.x == b.x) return a.y < b.y;
    else return a.x < b.x;
}
bool cmp2(const int& a, const int& b) {
    return p[a].y < p[b].y;
}
int dist(int i, int j) {
    int xx = p[i].x - p[j].x;
    int yy = p[i].y - p[j].y;
    return xx * xx + yy * yy;
}
int ans_i, ans_j;
int ans_k1, ans_k2;
int min_dis;
int Merge(int l, int r) {
    int d = INF;
    if (l == r) return d;

    int mid = (l + r) >> 1;
    int d1 = Merge(l, mid);
    int d2 = Merge(mid + 1, r);
    d = min(d1, d2);
    min_dis = min(min_dis, d);
    int k = 0;
    for (int i = l; i <= r; i++) {
        if (mid != i && p[mid].id == p[i].id) continue;
        int len = abs(p[mid].x - p[i].x);
        if (len * len < d) tp[++k] = i;
    }

    sort(tp + 1, tp + 1 + k, cmp2);
    for (int i = 1; i <= k; i++) {
        for (int j = i + 1; j <= k; j++) {
            if (p[tp[j]].id == p[tp[i]].id) continue;
            int len = p[tp[j]].y - p[tp[i]].y;
            if (len * len >= d) break;
            int d3 = dist(tp[i], tp[j]);
            if (d3 < min_dis) {
                min_dis = d3;
                ans_i = p[tp[j]].id; ans_k1 = p[tp[j]].k;
                ans_j = p[tp[i]].id; ans_k2 = p[tp[i]].k;
            }
            if (d3 < d) d = d3;
        }
    }
    return d;
}
int change(int x) {
    if (x == 1) return 4;
    else if (x == 2) return 3;
    else if (x == 3) return 2;
    else return 1;
}
int main() {
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        p[i].x = x; p[i].y = y;
        p[i].id = i; p[i].k = 1;
    }
    int cnt = n;
    for (int i = 1; i <= cnt; i++) {
        for (int j = 2; j <= 4; j++) {
            ++n;
            p[n].id = i; p[n].k = j;
            p[n].x = p[i].x * dx[j];
            p[n].y = p[i].y * dy[j];
        }
    }
    sort(p + 1, p + 1 + n, cmp1);
    min_dis = INF;
    Merge(1, n);
    ans_k2 = change(ans_k2);
//    printf("%lld\n", mmin);
    printf("%d %d %d %d\n", ans_i, ans_k1, ans_j, ans_k2);
    return 0;
}
上一篇:数据结构知识总结(一)--算法分析


下一篇:拓扑排序详解 (?