http://poj.org/problem?id=3241

曼哈顿距离最小生成树模板题。

核心思想是把坐标系转3次,以及以横坐标为第一关键字,纵坐标为第二关键字排序后,从后往前扫。扫完一个点就把它插到树状数组的y-x位置上,权值为x+y。查询时查询扫过的所有点满足ydone-xdone>=ynow-xnow时,直接是树状数组中的的一个后缀区间,从后往前扫保证了区间内的这些点都在当前点的y轴向右扫45度的范围内。树状数组实现查询x+y的最小值,以及此最小值对应原数组中的位置,方便建图连边。

模板是抄的别人的QAQ

时间复杂度$O(n\log n)$

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100003;
int in() {
int k = 0, fh = 1; char c = getchar();
for(; c < '0' || c > '9'; c = getchar())
if (c == '-') fh = -1;
for(; c >= '0' && c <= '9'; c = getchar())
k = (k << 3) + (k << 1) + c - '0';
return k * fh;
} struct Point {
int x, y, id;
bool operator < (const Point &A) const {
return x == A.x ? y < A.y : x < A.x;
}
} P[N];
struct Bits {
int mn, pos;
void init() {mn = 0x7fffffff; pos = -1;}
} bit[N];
int tot;
struct Edge {
int u, v, dis;
bool operator < (const Edge &A) const {
return dis < A.dis;
}
} E[N << 2];
void add(int a, int b, int c) {E[++tot] = (Edge) {a, b, c};} int n, fa[N], k;
int find(int x) {
if (fa[x] == x) return x;
fa[x] = find(fa[x]); return fa[x];
} int dist(int x, int y) {
return abs(P[x].x - P[y].x) + abs(P[x].y - P[y].y);
} void update(int x, int num, int pos) {
for(; x; x -= (x & (-x)))
if (num < bit[x].mn)
bit[x].mn = num, bit[x].pos = pos;
} int m;
int query(int x) {
int ans = 0x7fffffff, pos = -1;
for(x; x <= m; x += (x & (-x)))
if (bit[x].mn < ans)
ans = bit[x].mn, pos = bit[x].pos;
return pos;
} int a[N], H[N], cnt;
int solve() {
for(int change = 0; change < 4; ++change) {
if (change == 1 || change == 3)
for(int i = 1; i <= n; ++i) swap(P[i].x, P[i].y);
else if (change == 2)
for(int i = 1; i <= n; ++i) P[i].x = -P[i].x; sort(P + 1, P + n + 1);
for(int i = 1; i <= n; ++i)
a[i] = H[i] = P[i].y - P[i].x;
cnt = n;
sort(H + 1, H + cnt + 1);
cnt = unique(H + 1, H + cnt + 1) - H;
for(int i = 1; i <= cnt; ++i) bit[i].init();
int pos, tmp; m = cnt;
for(int i = n; i > 0; --i) {
pos = lower_bound(H + 1, H + cnt, a[i]) - H;
tmp = query(pos);
if (tmp != -1)
add(P[i].id, P[tmp].id, dist(i, tmp));
update(pos, P[i].x + P[i].y, i);
}
}
sort(E + 1, E + tot + 1);
cnt = n - k;
for(int i = 1; i <= n; ++i) fa[i] = i;
int u, v;
for(int i = 1; i <= tot; ++i) {
u = find(E[i].u); v = find(E[i].v);
if (u != v) {
--cnt;
fa[u] = v;
if (cnt == 0) return E[i].dis;
}
}
} int main() {
while (~scanf("%d%d", &n, &k)) {
tot = 0;
for(int i = 1; i <= n; ++i) {
P[i].x = in(); P[i].y = in();
P[i].id = i;
}
printf("%d\n", solve());
}
return 0;
}

【POJ 3241】Object Clustering 曼哈顿距离最小生成树的更多相关文章

  1. POJ 3241 Object Clustering 曼哈顿最小生成树

    Object Clustering   Description We have N (N ≤ 10000) objects, and wish to classify them into severa ...

  2. poj 3241 Object Clustering (曼哈顿最小生成树)

    Object Clustering Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 2640   Accepted: 806 ...

  3. POJ 3241Object Clustering曼哈顿距离最小生成树

    Object Clustering Description We have N (N ≤ 10000) objects, and wish to classify them into several ...

  4. POJ 3241 Object Clustering(Manhattan MST)

    题目链接:http://poj.org/problem?id=3241 Description We have N (N ≤ 10000) objects, and wish to classify ...

  5. 51nod 1213 二维曼哈顿距离最小生成树

    1213 二维曼哈顿距离最小生成树 基准时间限制:4 秒 空间限制:131072 KB 分值: 160 难度:6级算法题  收藏  关注 二维平面上有N个坐标为整数的点,点x1 y1同点x2 y2之间 ...

  6. 曼哈顿距离最小生成树 codechef Dragonstone

    曼哈顿距离最小生成树 codechef Dragonstone 首先,对于每一个点来说有用的边只有它向它通过 x=0,y=0,y=x,y=-x 切出来的八个平面的最近点. 证明 我不会 反正当结论记住 ...

  7. [51nod1213]二维曼哈顿距离最小生成树

    二维平面上有N个坐标为整数的点,点x1 y1同点x2 y2之间的距离为:横纵坐标的差的绝对值之和,即:Abs(x1 - x2) + Abs(y1 - y2)(也称曼哈顿距离).求这N个点所组成的完全图 ...

  8. POJ 3241 曼哈顿距离最小生成树 Object Clustering

    先上几个资料: 百度文库有详细的分析和证明 cxlove的博客 TopCoder Algorithm Tutorials #include <cstdio> #include <cs ...

  9. POJ3241 Object Clustering 曼哈顿最小生成树

    题意:转换一下就是求曼哈顿最小生成树的第n-k条边 参考:莫涛大神的论文<平面点曼哈顿最小生成树> /* Problem: 3241 User: 96655 Memory: 920K Ti ...

随机推荐

  1. vmware虚拟机 32位Ubuntu 安装matlab_R2012A问题小记

    最近由于学校课程的需要,所以在Ubuntu上捣腾了一下matlab,经历曲折,记录一下,希望能让大家少跳点坑.先分享一个有效的下载链接: http://www.matlab.org.cn/Downlo ...

  2. ArrayList如何实现线程安全

    一:使用synchronized关键字,这个大家应该都很熟悉了,不解释了: 二:使用Collections.synchronizedList();使用方法如下: 假如你创建的代码如下:List< ...

  3. 当手机被PS掉,人们看到的是手中的灵魂

    Eric Pickersgill是一名摄影师,最近喜欢拍摄并记录人们使用智能手机的情景,不过不同的是,在最终作品中会将手机从人们手中PS掉,一刹那会进入一个奇怪的世界.黑白照片也极具冲击力. 每个人神 ...

  4. [No00003E]26个字母暗藏的单词秘密

    个字母暗藏的单词秘密 人们普通认为:英语是拼音文字,因而与象形无关.但是,实际上,即使作为拼音文字,其字母的来源也与象形有关.根据笔者十多年的研究结果,英语中的二十六个字母每个字母都有其象形意义,而且 ...

  5. ES5特性Object.seal

    一个对象在默认状态下: 1,extensible:可扩展(可以添加新的属性) 2,configurable:可配置(可以改变原有属性的特性,比如修改属性的enumerable) Object.seal ...

  6. C# 根据正则表达式来判断输入的是不是数字

    最近在做输入判断的时候出现了一个需要判断输入合法性的问题,就是判断输入的是不是数字,判断方法是根据正则表达式来判断,具体方法如下: private bool IsRightNum(string str ...

  7. SQL 按特定字段值排序

    SQL 按特定字段值排序的代码,有需要的朋友可以参考下. id, name shandong01 name1 shandong02 name2 shandong03 name3 beijing01 n ...

  8. BZOJ 4241 历史研究

    Description IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. ...

  9. 【转】$_POST 与 php://input的区别分析

    $data = file_get_contents("php://input"); php://input 是个可以访问请求的原始数据的只读流. POST 请求的情况下,最好使用 ...

  10. Session一次错误记录

    /// <summary>        /// 验证登录状态是否已失效        /// </summary>        /// <returns>< ...