[bzoj1941][kd-tree]Hide and Seek

本文介绍了一个捉迷藏游戏的算法解决方案,利用KdTree数据结构优化搜索过程,实现快速查找最近和最远点对,适用于大规模数据集。

Description

小猪iPig在PKU刚上完了无聊的猪性代数课,天资聪慧的iPig被这门对他来说无比简单的课弄得非常寂寞,为了消除寂寞感,他决定和他的好朋友giPi(鸡皮)玩一个更加寂寞的游戏—捉迷藏。
但是,他们觉得,玩普通的捉迷藏没什么意思,还是不够寂寞,于是,他们决定玩寂寞无比的螃蟹版捉迷藏,顾名思义,就是说他们在玩游戏的时候只能沿水平或垂直方向走。一番寂寞的剪刀石头布后,他们决定iPig去捉giPi。由于他们都很熟悉PKU的地形了,所以giPi只会躲在PKU内n个隐秘地点,显然iPig也只会在那n个地点内找giPi。游戏一开始,他们选定一个地点,iPig保持不动,然后giPi用30秒的时间逃离现场(显然,giPi不会呆在原地)。然后iPig会随机地去找giPi,直到找到为止。由于iPig很懒,所以他到总是走最短的路径,而且,他选择起始点不是随便选的,他想找一个地点,使得该地点到最远的地点和最近的地点的距离差最小。iPig现在想知道这个距离差最小是多少。
由于iPig现在手上没有电脑,所以不能编程解决这个如此简单的问题,所以他马上打了个电话,要求你帮他解决这个问题。iPig告诉了你PKU的n个隐秘地点的坐标,请你编程求出iPig的问题。

Input

第一行输入一个整数N 第2~N+1行,每行两个整数X,Y,表示第i个地点的坐标

Output

一个整数,为距离差的最小值。

Sample Input

4
0 0
1 0
0 1
1 1

Sample Output

1

HINT

对于30%的数据,N<=1000 对于100%的数据,N<=500000,0<=X,Y<=10^8 保证数据没有重点保证N>=2

题解

其实我看度娘提供给我的kdtree的blog还是迷迷糊糊不懂的
所以永远不要上度娘查专题
看题哇塞最近最远点对耶,我枚举枚举枚举哈哈哈哈哈哈哈n<=500000
**,高级数据结构??kdtree是啥???
通过一个中午的钻研我终于明白了。。这玩意其实就是一个高级的暴力。相当于在k维空间上进行分块,然后每一次估价左孩子的块和右孩子的块可能存在的答案更优秀。优的那个块就优先查找,之后观察更新后的答案是否比估价差的答案好来决定访不访问那个差的块。于是这就是Kdtree了。。
这个大暴力却能证明均摊复杂度是sqrt(n)的
不多说了。直接对这个二维平面建kdtree,然后暴力枚举每个点,搜距离最近最远的点一减就好了。。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int inf=999999999;
struct node
{
    int lc,rc,d[2],mx[2],mn[2];
}tr[1110000];
void update(int x)
{
    int lc=tr[x].lc,rc=tr[x].rc;
    if(lc)
    {
        tr[x].mx[0]=max(tr[x].mx[0],tr[lc].mx[0]);
        tr[x].mn[0]=min(tr[x].mn[0],tr[lc].mn[0]);
        tr[x].mx[1]=max(tr[x].mx[1],tr[lc].mx[1]);
        tr[x].mn[1]=min(tr[x].mn[1],tr[lc].mn[1]);
    }
    if(rc)
    {
        tr[x].mx[0]=max(tr[x].mx[0],tr[rc].mx[0]);
        tr[x].mn[0]=min(tr[x].mn[0],tr[rc].mn[0]);
        tr[x].mx[1]=max(tr[x].mx[1],tr[rc].mx[1]);
        tr[x].mn[1]=min(tr[x].mn[1],tr[rc].mn[1]);
    }
}
int cmpd;
bool cmp(node n1,node n2)
{
    return n1.d[cmpd]<n2.d[cmpd] || n1.d[cmpd]==n2.d[cmpd] && n1.d[cmpd^1]<n2.d[cmpd^1];
}
int bt(int l,int r,int d)
{
    int mid=(l+r)/2,now;
    cmpd=d;now=mid;
    nth_element(tr+l,tr+mid,tr+r+1,cmp);//取出当前平面的中值 
    tr[now].mx[0]=tr[now].mn[0]=tr[now].d[0];
    tr[now].mx[1]=tr[now].mn[1]=tr[now].d[1];
    if(l<mid)tr[now].lc=bt(l,mid-1,d^1);//儿子就要用另一个平面 
    if(mid<r)tr[now].rc=bt(mid+1,r,d^1);//同理 
    update(now);
    return now;
}
//int X[510000],Y[510000];
int nowx,nowy,root,n;
int minn,maxx;
//建树,分别用两个平面来划分块 
int dismin(int now,int x,int y)//估价函数,判断答案可能出现在now块的最小值 
{
    int d=0;
    if(x>tr[now].mx[0])d+=x-tr[now].mx[0];
    if(x<tr[now].mn[0])d+=tr[now].mn[0]-x;
    if(y>tr[now].mx[1])d+=y-tr[now].mx[1];
    if(y<tr[now].mn[1])d+=tr[now].mn[1]-y;
    return d;
}
void solmin(int now)
{
    int dl=inf,dr=inf;
    int d0=abs(nowx-tr[now].d[0])+abs(nowy-tr[now].d[1]);
    if(d0)minn=min(minn,d0);
    if(tr[now].lc)dl=dismin(tr[now].lc,nowx,nowy);
    if(tr[now].rc)dr=dismin(tr[now].rc,nowx,nowy);
    if(dl<dr)
    {
        if(dl<minn)solmin(tr[now].lc);//先跑最有可能出现的 
        if(dr<minn)solmin(tr[now].rc);//再跑第二有可能出现的 
    }
    else
    {
        if(dr<minn)solmin(tr[now].rc);
        if(dl<minn)solmin(tr[now].lc);
    }
}
int dismax(int now,int x,int y)
{
    int d=0;
    d+=max(abs(tr[now].mx[0]-x),abs(tr[now].mn[0]-x));
    d+=max(abs(tr[now].mx[1]-y),abs(tr[now].mn[1]-y));
    return d;
}
void solmax(int now)
{
    int dl=-inf,dr=-inf;
    int d0=abs(tr[now].d[0]-nowx)+abs(tr[now].d[1]-nowy);
    if(d0)maxx=max(maxx,d0);
    if(tr[now].lc)dl=dismax(tr[now].lc,nowx,nowy);
    if(tr[now].rc)dr=dismax(tr[now].rc,nowx,nowy);
    if(dl>dr)
    {
        if(dl>maxx)solmax(tr[now].lc);
        if(dr>maxx)solmax(tr[now].rc);
    }
    else
    {
        if(dr>maxx)solmax(tr[now].rc);
        if(dl>maxx)solmax(tr[now].lc);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d",&tr[i].d[0],&tr[i].d[1]);
    root=bt(1,n,0);
    int ans=inf;
    for(int i=1;i<=n;i++)
    {
        nowx=tr[i].d[0];nowy=tr[i].d[1];
        minn=inf;maxx=0;
        solmin(root);solmax(root);
        ans=min(ans,maxx-minn);
    }
    printf("%d\n",ans);
    return 0;
}
传送带损坏与对象检测数据集 一、基础信息 • 数据集名称:传送带损坏与对象检测数据集 • 图片数量: 训练集:645张图片 验证集:185张图片 测试集:92张图片 总计:922张工业监控图片 • 训练集:645张图片 • 验证集:185张图片 • 测试集:92张图片 • 总计:922张工业监控图片 • 分类类别: Hole(孔洞):传送带表面的孔洞损坏。 Human(人类):工作区域中的人类,用于安全监控。 Other Objects(其他对象):非预期对象,可能引起故障。 Puncture(刺穿):传送带被刺穿的损坏。 Roller(滚筒):传送带滚筒部件。 Tear(撕裂):传送带撕裂损坏。 impact damage(冲击损坏):由于冲击导致的损坏。 patch work(修补工作):已修补的区域。 • Hole(孔洞):传送带表面的孔洞损坏。 • Human(人类):工作区域中的人类,用于安全监控。 • Other Objects(其他对象):非预期对象,可能引起故障。 • Puncture(刺穿):传送带被刺穿的损坏。 • Roller(滚筒):传送带滚筒部件。 • Tear(撕裂):传送带撕裂损坏。 • impact damage(冲击损坏):由于冲击导致的损坏。 • patch work(修补工作):已修补的区域。 • 标注格式:YOLO格式,包含边界框和类别标签,适用于目标检测任务。 • 数据格式:图像数据来源于工业监控系统,适用于计算机视觉分析。 二、适用场景 • 工业自动化检测系统开发:用于构建自动检测传送带损坏和异物的AI模型,实现实时监控和预防性维护,减少停机时间。 • 安全监控应用:识别人类和其他对象,提升工业环境的安全性,避免事故和人员伤害。 • 学术研究与创新:支持计算机视觉在制造业、物流和自动化领域的应用研究,促进AI技术与工业实践的融合。 • 教育与培训:可用于培训AI模型或作为工业工程和自动化教育的案例数据,帮助学习者理解实际应用场景。 三、数据集优势 • 多样化的类别覆盖:包含8个关键类别,涵盖多种损坏类型和对象,确保模型能够处理各种实际工业场景,提升泛化能力。 • 精准的标注质量:采用YOLO格式,边界框标注准确,由专业标注人员完成,保证数据可靠性和模型训练效果。 • 强大的任务适配性:兼容主流深度学习框架(如YOLO、TensorFlow、PyTorch),可直接用于目标检测任务,并支持扩展至其他视觉任务需求。 • 突出的工业价值:专注于工业传送带系统的实际需求,帮助提升生产效率、降低维护成本,并增强工作场所安全,具有较高的实际应用价值。
一、基础信息 • 数据集名称:垃圾废弃物目标检测数据集 • 图片数量: 训练集:1124张图片 验证集:375张图片 总计:1499张图片 • 训练集:1124张图片 • 验证集:375张图片 • 总计:1499张图片 • 分类类别:包含60多个垃圾和废弃物类别,如气溶胶、铝泡罩包装、电池、破碎玻璃、卡片泡罩包装、香烟、透明塑料瓶、瓦楞纸箱、薯片袋、一次性食品容器、一次性塑料杯、饮料罐、饮料纸盒、鸡蛋盒、泡沫杯、泡沫食品容器、食品罐、食物垃圾、垃圾袋、玻璃瓶、玻璃杯、玻璃罐、杂志纸、餐盒、金属瓶盖、金属盖、普通纸、其他纸箱、其他塑料、其他塑料瓶、其他塑料容器、其他塑料杯、其他塑料包装、纸袋、纸杯、纸吸管、披萨盒、塑料瓶盖、塑料薄膜、塑料手套、塑料盖、塑料吸管、塑料餐具、聚丙烯袋、拉环、绳子、废金属、鞋子、一次性购物袋、六罐环、涂抹管、可挤压管、泡沫塑料片、纸巾、厕纸管、特百惠、未标记垃圾、包装纸等。 • 标注格式:YOLO格式,包含边界框和类别标签,适用于目标检测任务。 • 数据格式:图片来源于实际场景,细节清晰。 二、适用场景 • 垃圾自动分类系统开发:数据集支持目标检测任务,帮助构建能够自动识别和分类垃圾物品的AI模型,用于智能垃圾桶或回收系统,提升废弃物管理效率。 • 环保应用研发:集成至环保和废弃物管理应用,提供实时垃圾识别功能,促进回收和环境保护,支持可持续发展倡议。 • 学术研究与创新:支持计算机视觉与环保领域的交叉研究,助力发表垃圾识别和AI技术相关学术论文,推动技术创新。 • 教育与培训:可用于学校或培训机构,作为垃圾分类和AI目标检测教学的重要资源,培养环保意识和技术能力。 三、数据集优势 • 精准标注与多样性:每张图片经过准确标注,确保边界框定位精确;包含多种垃圾类别,覆盖常见废弃物,提升模型的泛化能力和鲁棒性。 • 任务适配性强:标注兼容主流深度学习框架(如YOLO等),可直接用于目标检测任务,并支持扩展到其他视觉任务,如分类或分割。 • 实际应用价值:专注于垃圾识别,为环保、废弃物管理和回收提供重要数据支撑,有助于减少污染和促进循环经济。
水下垃圾实例分割数据集 一、基础信息 • 数据集名称:水下垃圾实例分割数据集 • 图片数量: 训练集:1049张图片 验证集:300张图片 测试集:150张图片 总计:1499张图片 • 训练集:1049张图片 • 验证集:300张图片 • 测试集:150张图片 • 总计:1499张图片 • 分类类别: Aerosol(气溶胶罐) Aluminium blister pack(铝泡罩包装) Aluminium foil(铝箔) Battery(电池) Broken glass(碎玻璃) Carded blister pack(卡式泡罩包装) Cigarette(香烟) Clear plastic bottle(透明塑料瓶) Corrugated carton(瓦楞纸箱) Crisp packet(薯片袋) Disposable food container(一次性食品容器) Disposable plastic cup(一次性塑料杯) Drink can(饮料罐) Drink carton(饮料纸盒) Egg carton(鸡蛋盒) Foam cup(泡沫杯) Foam food container(泡沫食品容器) Food Can(食品罐) Food waste(食物垃圾) Garbage bag(垃圾袋) Glass bottle(玻璃瓶) Glass cup(玻璃杯) Glass jar(玻璃罐) Magazine paper(杂志纸) Meal carton(餐盒) Metal bottle cap(金属瓶盖) Metal lid(金属盖子) Normal paper(普通纸) Other carton(其他纸盒) Other plastic(其他塑料) Other plastic bottle(其他塑料瓶) Other plastic container(其他塑料容器) Other plastic cup(其他塑料杯) Other plastic wrapper(其他塑料包装) Paper bag(纸袋) Paper cup(纸杯) Paper straw(纸吸管) Pizza box(披萨盒) Plastic bottle cap(塑料瓶盖) Plastic film(塑料薄膜) Plastic gloves(塑料手套) Plastic lid(塑料盖子) Plastic straw(塑料吸管) Plastic utensils(塑料餐具) Polypropylene bag(聚丙烯袋) Pop tab(易拉罐拉环) Rope - strings(绳子-字符串) Scrap metal(废金属) Shoe(鞋子) Single-use carrier bag(一次性购物袋) Six pack rings(六罐环) Spread tub(涂抹桶) Squeezable tube(可挤压管) Styrofoam piece(泡沫塑料片) Tissues(纸巾) Toilet tube(卫生纸卷) Tupperware(特百惠) Unlabeled litter(未标记垃圾) Wrapping paper(包装纸) • Aerosol(气溶胶罐) • Aluminium blister pack(铝泡罩包装) • Aluminium foil(铝箔) • Battery(电池) • Broken glass(碎玻璃) • Carded blister pack(卡式泡罩包装) • Cigarette(香烟) • Clear plastic bottle(透明塑料瓶) • Corrugated carton(瓦楞纸箱) • Crisp packet(薯片袋) • Disposable food container(一次性食品容器) • Disposable plastic cup(一次性塑料杯) • Drink can(饮料罐) • Drink carton(饮料纸盒) • Egg carton(鸡蛋盒) • Foam cup(泡沫杯) • Foam food container(泡沫食品容器) • Food Can(食品罐) • Food waste(食物垃圾) • Garbage bag(垃圾袋) • Glass bottle(玻璃瓶) • Glass cup(玻璃杯) • Glass jar(玻璃罐) • Magazine paper(杂志纸) • Meal carton(餐盒) • Metal bottle cap(金属瓶盖) • Metal lid(金属盖子) • Normal paper(普通纸) • Other carton(其他纸盒) • Other plastic(其他塑料) • Other pl
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值