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. QC学习一:Windows环境中Quality Center 9.0安装详解

    一.安装前准备 1.安装环境:windows XP.SQL Server2005 2.准备安装文件:Quality Center 9.0 (qc10以上,包括qc10,qc只支持安装在服务器操作系统上 ...

  2. PHPstudy和ecshop的安装和使用

    PHPstudy和ecshop: phpStudy是一个PHP调试环境的程序集成包. 该程序包集成最新的Apache+PHP+MySQL+phpMyAdmin+ZendOptimizer,一次性安装, ...

  3. VS中的jQuery

    jquery中用attr()方法来获取和设置元素属性,attr是attribute(属性)的缩写,在jQuery DOM操作中会经常用到attr(),attr()有4个表达式.1. attr( 属性名 ...

  4. java代码封装与编译

    代码封装: 在这个java程序内调用另一个类 在arrayTool中把这两个函数封装起来. 编译顺序:(由下文可知应该是先进行语法检查再进行编译) 先编译ArrayTool再编译ArrayOperat ...

  5. IOS

    网上课程:http://www.zhijieketang.com/ edu.51cto.com 码云:http://git.oschina.net/名字 Gesture:https://www.osc ...

  6. 对于多个列的转行(一个值均匀分布在两个列中),对于个别字段通过取别名,join方式解决。

    例如,这个表的结构: select r.* from RPDATA2016 r WHERE r.data_bbid='HY052' 如图 对于最后两列,如果是字符类型,会存在倒数第二列,是数字类型,会 ...

  7. Oracle 多表update

    今天凌晨因为要在数据库里做一些操作,是关于两表关联的update,但语句怎么写都不正确,老是报错,于是心惊肉跳(就怕不能及时完成操作)去查了一下,NND,原来把SQL写成了在SQL Server下面的 ...

  8. CoreAnimation笔记

    核心动画继承结构 CoreAnimation Core Animation是直接作用在CALayer上的(并非UIView上)非常强大的跨Mac OS X和iOS平台的动画处理API,Core Ani ...

  9. 2178 表达式运算Cuties

    2178 表达式运算Cuties  时间限制: 1 s  空间限制: 32000 KB  题目等级 : 大师 Master 题解       题目描述 Description 给出一个表达式,其中运算 ...

  10. java反射详解(转)

    本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理论,会有更好的理解. 下面开始正文. [案例1]通过一个对象 ...