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

Time Limit: 20 Sec  Memory Limit: 128 MB

Description

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

Input

第一行两个数 N M

以后M行,每行3个数 t x y

如果t=1 那么放下一个黑色棋子

如果t=2 那么放下一个白色棋子

Output

对于每个T=2 输出一个最小距离

Sample Input

2 3
1 1
2 3
2 1 2
1 3 3
2 4 2

Sample Output

1
2

HINT

kdtree可以过

Source

照着zgz233打了一遍板子qaq

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define inf 1000000007
#define ll long long
#define N 1000010
inline int rd()
{
    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;
}
struct qaz
{
    int d[2],mn[2],mx[2],l,r;
    int& operator[](int x){return d[x];}
}p[N],tr[N],T;
int D;
bool operator <(qaz a,qaz b){return a[D]<b[D];}
int rt;
#define ls tr[x].l
#define rs tr[x].r
inline void upd(int x)
{
    for(int i=0;i<2;i++)
    {
        if(ls) tr[x].mn[i]=min(tr[x].mn[i],tr[ls].mn[i]),tr[x].mx[i]=max(tr[x].mx[i],tr[ls].mx[i]);
        if(rs) tr[x].mn[i]=min(tr[x].mn[i],tr[rs].mn[i]),tr[x].mx[i]=max(tr[x].mx[i],tr[rs].mx[i]);
    }
}
int build(int l,int r,int t)
{
    D=t;
    int mid=l+r>>1;
    nth_element(p+l,p+mid,p+r+1);
    tr[mid]=p[mid];
    for(int i=0;i<2;i++) tr[mid].mn[i]=tr[mid].mx[i]=tr[mid][i];
    if(l<mid) tr[mid].l=build(l,mid-1,t^1);
    if(mid<r) tr[mid].r=build(mid+1,r,t^1);
    upd(mid);return mid;
}
int n,m;
void ins(int x,int t)
{
    if(T[t]<tr[x][t])
    {
        if(ls) ins(ls,t^1);
        else{ls=++n,tr[n]=T;}
    }
    else
    {
        if(rs) ins(rs,t^1);
        else{rs=++n,tr[n]=T;}
    }
    upd(x);
}
int ans;
int dis(qaz a,qaz b){return abs(a[0]-b[0])+abs(a[1]-b[1]);}
int gtdis(qaz a,qaz b)
{
    int ji=0;
    for(int i=0;i<2;i++)
        ji+=max(0,b.mn[i]-a[i])+max(0,a[i]-b.mx[i]);
    return ji;
}
void fd(int x,int t)
{
    int d=dis(tr[x],T),dl=inf,dr=inf;
    ans=min(d,ans);
    if(ls) dl=gtdis(T,tr[ls]);
    if(rs) dr=gtdis(T,tr[rs]);
    if(dl<dr)
    {
        if(dl<ans) fd(ls,t^1);
        if(dr<ans) fd(rs,t^1);
    }
    else
    {
        if(dr<ans) fd(rs,t^1);
        if(dl<ans) fd(ls,t^1);
    }
}
int main()
{
    n=rd();m=rd();
    for(int i=1;i<=n;i++) p[i][0]=rd(),p[i][1]=rd();
    rt=build(1,n,0);
    int op,x,y;
    while(m--)
    {
        T.l=T.r=0;op=rd();
        T.mn[0]=T.mx[0]=T[0]=rd();
        T.mn[1]=T.mx[1]=T[1]=rd();
        if(op==1) ins(rt,0);
        else
        {
            ans=inf;
            fd(rt,0);
            printf("%d\n",ans);
        }
    }
    return 0;
}
时间: 2024-08-06 05:28:04

bzoj 2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 --kdtree的相关文章

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

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

【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.....显然我脑残了....写到一半发现这

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摆棋子-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摆棋子(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摆棋子(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摆棋子——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

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摆棋子 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>