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. Servlet分页技术

    这是看韩顺平老师的servlet视频,自己动手写的,楼主看韩顺平老师的servlet是2006制作的,用的是sql server数据库,自己又用的是oracle数据库,所以怕有的同学遇到同样的问题,不 ...

  2. NOIP水题合集[3/未完待续]

    NOIP2008pj传球游戏 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球, ...

  3. 转: windows 10使用原生linux bash命令行

    转: https://www.zybuluo.com/pandait/note/337430 windows 10使用原生linux bash命令行 linux bash windows-10 第一时 ...

  4. MySQL注射的过滤绕过技巧[1]

    SQL注射的绕过技巧较多,此文仅做一些简单的总结. 前文已经提到,最好利用的注射点: 支持Union 可报错 支持多行执行.可执行系统命令.可HTTP Request等额外有利条件 若非以上类型,则可 ...

  5. Xcode 编译的哪些错误

    1.error: macro names must be identifiers YourProject_prefix.pch 原因: 因为你弄脏了预处理器宏,在它处于<Multiple Val ...

  6. HTML 学习笔记 CSS3(过度 transition)

    通过 CSS3,我们可以在不使用 Flash 动画或 JavaScript 的情况下,当元素从一种样式变换为另一种样式时为元素添加效果.请把鼠标移动到下面的元素上: 先看一下这个代码 实现旋转放大的效 ...

  7. AIO 简介

    from:http://blog.chinaunix.net/uid-11572501-id-2868654.html   Linux的I/O机制经历了一下几个阶段的演进: 1. 同步阻塞I/O: 用 ...

  8. Java 日志性能优化

    1. 选择合理的日志级别.合理控制日志内容 2. 控制日志的输出内容和格式 logger.debug("Entry number: " + i + " is " ...

  9. android小游戏 飞机躲子弹

    最近android老师让每人写一个小东西,因为之前学awt时写过一个java版的飞机躲子弹,所以这次想写成android版的. 文件直接导入就行http://files.cnblogs.com/fil ...

  10. githup上传代码

    把自己本地东西上传到GitHup上. 本文内容来自于http://blog.csdn.net/yuanzichao/article/details/44922593 1.安装msysgit和Torto ...