bzoj 2648 SJY摆棋子——KDtree

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648

第一道KDtree!

学习资料:https://blog.csdn.net/zhl30041839/article/details/9277807

     https://www.cnblogs.com/galaxies/p/kdtree.html

这道题的代码是学习(抄)的这里的:https://blog.csdn.net/lych_cys/article/details/50809141

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+5,INF=0x3f3f3f3f;
int n,m,fx,rt,ans,tot;
struct Node{
    int x[2],y[2],p[2];//x:min y:max p:ps
}a[N>>1];
bool cmp(Node u,Node v){return u.p[fx]<v.p[fx];}
struct Kd{
    int c[N][2];Node s[N],q;//大家的儿子、根和唯一的询问
    void add(int cr,Node k)
    {    for(int i=0;i<2;i++) s[cr].x[i]=s[cr].y[i]=s[cr].p[i]=k.p[i];}
    void pshp(int cr)
    {
        int ls=c[cr][0],rs=c[cr][1];
        for(int i=0;i<2;i++)
        {
            if(ls)
                s[cr].x[i]=min(s[cr].x[i],s[ls].x[i]),
                s[cr].y[i]=max(s[cr].y[i],s[ls].y[i]);
            if(rs)
                s[cr].x[i]=min(s[cr].x[i],s[rs].x[i]),
                s[cr].y[i]=max(s[cr].y[i],s[rs].y[i]);
        }
    }
    void build(int &cr,int l,int r,int now)
    {
        int mid=l+r>>1;fx=now;
        nth_element(a+l,a+mid,a+r+1,cmp);
//        cr=mid;add(cr,a[mid]);//////cr=mid!
        cr=++tot;add(cr,a[mid]);
        if(l<mid)build(c[cr][0],l,mid-1,!now);///if()
        if(mid<r)build(c[cr][1],mid+1,r,!now);
        pshp(cr);
    }
    void insert(int &cr,int now)
    {
//        if(!cr){cr=++n;add(cr,q);return;}//cr=++n!
        if(!cr){cr=++tot;add(cr,q);return;}
        if(q.p[now]<s[cr].p[now])insert(c[cr][0],!now);
        else insert(c[cr][1],!now);
        pshp(cr);
    }
    int dist(int cr,Node k)//在区域内返回0
    {
        int ret=0;
        for(int i=0;i<2;i++)
            ret+=max(0,s[cr].x[i]-k.p[i])+max(0,k.p[i]-s[cr].y[i]);
        return ret;
    }
    void query(int cr,int now)
    {
        ans=min(ans,abs(s[cr].p[0]-q.p[0])+abs(s[cr].p[1]-q.p[1]));
        int dl=c[cr][0]?dist(c[cr][0],q):INF,dr=c[cr][1]?dist(c[cr][1],q):INF;
        if(dl<dr)
        { if(dl<ans)query(c[cr][0],!now); if(dr<ans)query(c[cr][1],!now);}
        else
        { if(dr<ans)query(c[cr][1],!now); if(dl<ans)query(c[cr][0],!now);}
    }
}kd;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d%d",&a[i].p[0],&a[i].p[1]);
    kd.build(rt,1,n,0);
    for(int i=1,op;i<=m;i++)
    {
        scanf("%d%d%d",&op,&kd.q.p[0],&kd.q.p[1]);
        if(op==1) kd.insert(rt,0);
        else {    ans=INF; kd.query(rt,0); printf("%d\n",ans);}
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Narh/p/9490321.html

时间: 2024-11-06 21:51:03

bzoj 2648 SJY摆棋子——KDtree的相关文章

BZOJ 2648(SJY摆棋子-KD_Tree)

2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1180  Solved: 391 [Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=5000

bzoj 2648: SJY摆棋子&amp;&amp;2716: [Violet 3]天使玩偶 --kdtree

Time Limit: 20 Sec  Memory Limit: 128 MB Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000个初始棋子.和M<=500000个操作.对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离.同一个格子可能有多个棋子

BZOJ 2648: SJY摆棋子

Descrption 平面求最近点...\(n\leqslant 5\times 10^5\) Solution KD-Tree. 双倍经验..BZOJ 2716: [Violet 3]天使玩偶 Code /************************************************************** Problem: 2648 User: BeiYu Language: C++ Result: Accepted Time:13864 ms Memory:32560

BZOJ 2648 SJY摆棋子 / 2716 Violet 3 天使玩偶 K-D树

题目大意:平面上有一些点,问一个点周围离它最近的点的曼哈顿距离是多少.支持动态加点. 思路:CDQ分治可以离线解决,但是SJY是卡CDQ的,天使玩偶可以过.毕竟K-D树的O(sqrt(n))的时间复杂度摆在那. K-D树理解起来其实不难,有k个维度的时候,每一层按照一个维度排序,取出按照这个维度排序的中位数,当作这个块的根,然后将这个块分开.还有一个比较重要的东西就是估价函数,这个函数根据不同的题可能不同.股价函数的主要用途就是对搜索进行剪枝,如果估价函数就已经大于当前的最优答案了,那就不用搜这

BZOJ 2648: SJY摆棋子(K-D Tree)

Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 6051  Solved: 2113[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000个初始棋子.和M<=5

BZOJ 2648 SJY摆棋子 K-Dimensional-Tree

题目大意:给定平面上的n个点,定义距离为曼哈顿距离,支持下列操作: 1.插入一个点 2.查询离一个点最近的点的距离 Hint说KDTree[可以]过,那么不写KDT还能写啥= = 我的CDQ分治可是T掉了啊= = 记住KDT发生TLE事件的时候不一定是常数问题 有可能写挂了= =(这不和莫队一样么233 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm>

BZOJ 2648 SJY摆棋子(KD树)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2716 [题目大意] 给出一些点,同时不断插入点和询问某点离插入点最近距离 [题解] 我们对于给定的点直接建树,之后动态插入查询即可,重建会超时, 直接插入就可以过了 [代码] #include <cstdio> #include <algorithm> using namespace std; const int N=1500000,INF=1e9; inline in

bzoj 2648 SJY摆棋子 cdq分治+树状数组

题面 题目传送门 解法 同bzoj2716 自己cdq写的还是丑啊,别人A掉了我T飞了 代码 #include <bits/stdc++.h> #define inf 1 << 30 #define N 1000010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x, y);} template <typename node>

【BZOJ2648】SJY摆棋子 [KD-tree]

SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N个初始棋子,和M个操作.对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的