[bzoj2648/2716]SJY摆棋子

平面上有n个点,要求支持插入一个点和查询一个点的最近点距离 n,m<=500000

用kdtree实现,但是复杂度貌似没法保证.....下次加一个替罪羊重建试试。

#include<iostream>
#include<cstdio>
#include<algorithm>
#define INF 2000000000
#define MN 1000000
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < ‘0‘ || ch > ‘9‘){ if(ch == ‘-‘) f = -1;  ch = getchar();}
    while(ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}
int n,now,m;
inline int abs(int x){return x<0?-x:x;}
struct P{
    int d[2],mx[2],mn[2],l,r;
    int& operator[](int x){return d[x];}
    bool operator<(const P&x)const{return d[now]<x.d[now];}
    friend int dis(P x,P y){return abs(x.d[0]-y.d[0])+abs(x.d[1]-y.d[1]);}
}t[MN+5];

struct KD_TREE{
    P p[MN+5],T;int ans;
    void update(int x)
    {
        int l=p[x].l,r=p[x].r;
        for(int i=0;i<2;i++)
        {
            if(l) p[x].mn[i]=min(p[x].mn[i],p[l].mn[i]),
                  p[x].mx[i]=max(p[x].mx[i],p[l].mx[i]);
            if(r) p[x].mn[i]=min(p[x].mn[i],p[r].mn[i]),
                  p[x].mx[i]=max(p[x].mx[i],p[r].mx[i]);
        }
    }
    void ins(int x,int th)
    {
        if(T[th]>=p[x][th])
        {
            if(p[x].r) ins(p[x].r,th^1);
            else
            {
                int r=p[x].r=++n;p[r]=T;
                for(int i=0;i<2;i++)
                    p[r].mn[i]=p[r].mx[i]=T[i];
            }
        }
        else
        {
            if(p[x].l) ins(p[x].l,th^1);
            else
            {
                int l=p[x].l=++n;p[l]=T;
                for(int i=0;i<2;i++)
                    p[l].mn[i]=p[l].mx[i]=T[i];
            }
        }
        update(x);
    }
    int getmn(P x)
    {
        int sum=0;
        for(int i=0;i<2;i++)
        {
            sum+=max(x.mn[i]-T[i],0);
            sum+=max(T[i]-x.mx[i],0);
        }
        return sum;
    }
    int build(int l,int r,int th)
    {
        int mid=l+r>>1;now=th;
        nth_element(t+l,t+mid,t+r+1);
        p[mid]=t[mid];
        for(int i=0;i<2;i++)
            p[mid].mx[i]=p[mid].mn[i]=p[mid][i];
        if(l<mid) p[mid].l=build(l,mid-1,th^1);
        if(mid<r) p[mid].r=build(mid+1,r,th^1);
        update(mid);
        return mid;
    }
    void querymn(int k)
    {
        ans=min(ans,dis(p[k],T));
        int dl=INF,dr=INF;
        if(p[k].l) dl=getmn(p[p[k].l]);
        if(p[k].r) dr=getmn(p[p[k].r]);
        if(dl>dr)
        {
            if(dr<ans) querymn(p[k].r);
            if(dl<ans) querymn(p[k].l);
        }
        else
        {
            if(dl<ans) querymn(p[k].l);
            if(dr<ans) querymn(p[k].r);
        }
    }
}kd;
int rt,ans=INF;

int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
        t[i][0]=read(),t[i][1]=read();
    rt=kd.build(1,n,0);
    for(int i=1;i<=m;i++)
    {
        int op=read();kd.T[0]=read();kd.T[1]=read();
        if(op==1) kd.ins(rt,0);
        else
        {
            kd.ans=INF;kd.querymn(rt);
            printf("%d\n",kd.ans);
        }
    }
    return 0;
}
时间: 2024-08-12 18:24:21

[bzoj2648/2716]SJY摆棋子的相关文章

【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个操作.对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的

【BZOJ-2648&amp;2716】SJY摆棋子&amp;天使玩偶 KD Tree

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

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

SJY摆棋子&amp;&amp;[Violet 3]天使玩偶

SJY摆棋子 https://www.lydsy.com/JudgeOnline/problem.php?id=2648 [Violet 3]天使玩偶 https://www.lydsy.com/JudgeOnline/problem.php?id=2716 参考博客:https://blog.csdn.net/Littlewhite520/article/details/78284697 KDtree模板题,带插入 1 #include<iostream> 2 #include<cst

【BZOJ】2648: SJY摆棋子 &amp; 2716: [Violet 3]天使玩偶(kdtree)

http://www.lydsy.com/JudgeOnline/problem.php?id=2716 http://www.lydsy.com/JudgeOnline/problem.php?id=2648 双倍经验题... kdtree裸题吧.....今天学了下kdtree...感觉挺简单的.... 其实就是对几何图形进行剖分建树,而特殊在于,x和y轴轮流剖....这样可以提供很好的性质以便于查找... (一开始脑补了个treap代替kdtree.....显然我脑残了....写到一半发现这

Bzoj2648 SJY摆棋子

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

【BZOJ2648】【kd_tree】SJY摆棋子

Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000个初始棋子.和M<=500000个操作.对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离.同一个格子可能有多个棋子. Input 第一行两个数 N M 以后M行,每行3个数 t x y 如果t=1

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

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

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个操作.对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离.同一个格子可能有多个棋子