Poj3241 Object Clustering

本文介绍了解决POJ3241问题的方法,该问题要求求解曼哈顿距离最小生成树上的第k大边。通过坐标变换、线段树和树状数组等手段进行优化。

Poj3241 Object Clustering

Position:


List

Description

  • 大意:求曼哈顿距离最小生成树上第k大(第n-k小)的边

Knowledge

参考曼哈顿距离最小生成树
http://blog.csdn.net/yjpyjp2014/article/details/52180707

Solution

分析:
1.由上面资料可知,每45度的范围只算一个最近点
2.看下面一种情况:
      case
对于下面那个点,上面的点在它的右上方。而它又在上面的点的左下方,故我们只需计算左上和右上,即角[0,180]的范围,每45度一个,每个点4个,故边数不超过4×n。
3-1.为了写代码的方便,我们每次将点翻转,只计算[45,90]范围的点。翻转:①第一次不翻②第二次将一个点的x与y交换(即沿y=x翻转,原本在[0,45]的点翻到了[45,90])③将x=-x,沿x=0翻转,左上翻到右上④
3-2.ZYT的写法(可能容易理解一点):我们只需考虑在一块区域内的点,其他区域内的点可以通过坐标变换“移动”到这个区域内。为了方便处理,我们考虑在y轴向右45度的区域。在某个点A(x0,y0)的这个区域内的点B(x1,y1)满足x1≥x0且y1-x1>y0-x0。这里对于边界我们只取一边,但是操作中两边都取也无所谓。那么|AB|=y1-y0+x1-x0=(x1+y1)-(x0+y0)。在A的区域内距离A最近的点也即满足条件的点中x+y最小的点。因此我们可以将所有点按x坐标排序,再按y-x离散,用线段树或者树状数组维护大于当前点的y-x的最小的x+y对应的点(也就是维护区间最小值)。时间复杂度O(NlogN)。至于坐标变换,一个比较好处理的方法是第一次直接做(R1==R5);第二次沿直线y=x翻转,即交换x和y坐标(R2==R6);第三次沿直线x=0翻转,即将x坐标取相反数(R7==R3);第四次再沿直线y=x翻转(R8==R4)。注意只需要做4次,因为边是双向的。
             ZYT
4.对于点(x,y)如果有一个点(x1,y1)在它的(45,90),只要满足y1-x1>y-x(证明:即用一条斜率为45的直线,过这个点,比截距的大小y=x+b,y-x=b,平面图知识qaq~)
5.按x坐标排序,从后往前扫,值域(y-x)树状数组,w记录的是曼哈顿距离,pos记录第几个点。

Notice

1.这是一个反的树状数组,c[i]记录i~i+lowbit(i)-1
2.因为只要求x~m的最小值,用树状数组可以

Code

// <ObjectClustering.cpp> - 08/11/16 16:35:38
// This file is made by YJinpeng,created by XuYike's black technology automatically.
// Copyright (C) 2016 ChangJun High School, Inc.
// I don't know what this program is.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#define MOD 1000000007
#define INF 1e9
#define EPS 1e-10
using namespace std;
typedef long long LL;
const int MAXN=10010;
const int MAXM=100010;
inline int max(int &x,int &y) {return x>y?x:y;}
inline int min(int &x,int &y) {return x<y?x:y;}
inline int getint() {
    register int w=0,q=0;register char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')q=1,ch=getchar();
    while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar();
    return q?-w:w;
}
int n,m,k,tot,cnt,x,pos;
int f[MAXN],hs[MAXN],t[MAXN];
struct Point{
    int x,y,id;
    void read(){x=getint();y=getint();}
    friend bool operator < (const Point &a,const Point &b) {
        return a.x==b.x?a.y<b.y:a.x<b.x;
    }
}p[MAXN];
struct Edge{
    int u,v,w;
    friend bool operator < (const Edge &a,const Edge &b){
        return a.w<b.w;
    }
}e[MAXN*4];
struct Bit{
    int w,pos;
    void Pre(){pos=-1,w=INF;}
}b[MAXN];
inline int Find(int x){return x==f[x]?x:f[x]=Find(f[x]);}
inline int Lowbit(int x){return x&(-x);}
int Dis(int a,int b){
    return abs(p[a].x-p[b].x)+abs(p[a].y-p[b].y);
}
int Query(int x){
    int M=INF,pos=-1;
    for(int i=x;i<=m;i+=Lowbit(i))
        if(b[i].w<M)M=b[i].w,pos=b[i].pos;
    return pos;
}
void Update(int x,int M,int pos){
    for(int i=x;i;i-=Lowbit(i))
        if(M<b[i].w)b[i].w=M,b[i].pos=pos;
}
void Insert(int u,int v,int w){
    e[++cnt].u=u;e[cnt].v=v;e[cnt].w=w;
}
void Caledge(){
    sort(p+1,p+1+n);
    for(int i=1;i<=n;i++)hs[i]=t[i]=p[i].y-p[i].x;
    sort(hs+1,hs+1+n);
    m=unique(hs+1,hs+1+n)-hs;
    for(int i=1;i<=m;i++)b[i].Pre();
    for(int i=n;i>=1;i--){
        x=lower_bound(hs+1,hs+1+m,t[i])-hs+1;
        pos=Query(x);
        if(pos!=-1)Insert(p[i].id,p[pos].id,Dis(i,pos));
        Update(x,p[i].x+p[i].y,i);
    }
}
void Kruskal(){
    sort(e+1,e+1+cnt);tot=0;
    for(int i=1;i<=n;i++)f[i]=i;
    for(int i=1;i<=cnt;i++){
        f[e[i].u]=Find(f[e[i].u]);
        f[e[i].v]=Find(f[e[i].v]);
        if(f[e[i].u]!=f[e[i].v])f[f[e[i].u]]=f[e[i].v],tot++;
        if(tot==k){printf("%d",e[i].w);break;}
    }
}
int main()
{
    freopen("ObjectClustering.in","r",stdin);
    freopen("ObjectClustering.out","w",stdout);
    n=getint();k=n-getint();
    for(int i=1;i<=n;i++)p[i].read(),p[i].id=i;
    for(int j=1;j<=4;j++){
        if(j==2||j==4)
            for(int i=1;i<=n;i++)swap(p[i].x,p[i].y);
        else if(j==3)
            for(int i=1;i<=n;i++)p[i].x=-p[i].x;
        Caledge();
    }
    Kruskal();
    return 0;
}

感谢

Friend ZYT的大力支持

采用PyQt5框架与Python编程语言构建图书信息管理平台 本项目基于Python编程环境,结合PyQt5图形界面开发库,设计实现了一套完整的图书信息管理解决方案。该系统主要面向图书馆、书店等机构的日常运营需求,通过模块化设计实现了图书信息的标准化管理流程。 系统架构采用典型的三层设计模式,包含数据存储层、业务逻辑层和用户界面层。数据持久化方案支持SQLite轻量级数据库与MySQL企业级数据库的双重配置选项,通过统一的数据库操作接口实现数据存取隔离。在数据建模方面,设计了包含图书基本信息、读者档案、借阅记录等核心数据实体,各实体间通过主外键约束建立关联关系。 核心功能模块包含六大子系统: 1. 图书编目管理:支持国际标准书号、中国图书馆分类法等专业元数据的规范化著录,提供批量导入与单条录入两种数据采集方式 2. 库存动态监控:实时追踪在架数量、借出状态、预约队列等流通指标,设置库存预警阈值自动提醒补货 3. 读者服务管理:建立完整的读者信用评价体系,记录借阅历史与违规行为,实施差异化借阅权限管理 4. 流通业务处理:涵盖借书登记、归还处理、续借申请、逾期计算等标准业务流程,支持射频识别技术设备集成 5. 统计报表生成:按日/月/年周期自动生成流通统计、热门图书排行、读者活跃度等多维度分析图表 6. 系统维护配置:提供用户权限分级管理、数据备份恢复、操作日志审计等管理功能 在技术实现层面,界面设计遵循Material Design设计规范,采用QSS样式表实现视觉定制化。通过信号槽机制实现前后端数据双向绑定,运用多线程处理技术保障界面响应流畅度。数据验证机制包含前端格式校验与后端业务规则双重保障,关键操作均设有二次确认流程。 该系统适用于中小型图书管理场景,通过可扩展的插件架构支持功能模块的灵活组合。开发过程中特别注重代码的可维护性,采用面向对象编程范式实现高内聚低耦合的组件设计,为后续功能迭代奠定技术基础。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值