题目链接

KD-Tree.因为插入过多点后可能会退化成链,所以左/右子树sz > α*整棵子树sz时对整棵子树进行重构。

树的节点数必须是3n?why?洛谷,BZOJ都这样。。(数据范围错了吧 和SYJ摆棋子一样n=5e5→_→)

但是n=5e5为什么仍要3倍空间(重构的话)。。迷。

吊打CDQ

[Upd] 为啥我以前写不怎么加fread。。

//65280kb	14368ms
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define alpha (0.75)
const int N=(3e5+5),INF=0x7fffffff; int n,Q,root,D_now,Ans,top,sk[N*2]; struct Point{
int d[2];
}p[N*2];
struct Node{
int ls,rs,sz,Min[2],Max[2];
Point pt;
}t[N*3];//? inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline bool cmp(const Point &a,const Point &b){
return a.d[D_now]<b.d[D_now];//||(a.d[D_now]==b.d[D_now]&&a.d[D_now^1]<b.d[D_now^1]);
}
inline int New_Node(){
return top?sk[top--]:++n;
}
inline void Init(int rt){
for(int i=0; i<2; ++i)
t[rt].Min[i]=t[rt].Max[i]=t[rt].pt.d[i];
}
inline void Update(int rt)
{
int ls=t[rt].ls,rs=t[rt].rs;
t[rt].sz=t[ls].sz+t[rs].sz+1;
for(int i=0; i<2; ++i){
if(ls) t[rt].Min[i]=std::min(t[rt].Min[i],t[ls].Min[i]), t[rt].Max[i]=std::max(t[rt].Max[i],t[ls].Max[i]);
if(rs) t[rt].Min[i]=std::min(t[rt].Min[i],t[rs].Min[i]), t[rt].Max[i]=std::max(t[rt].Max[i],t[rs].Max[i]);
}
}
int Build(int l,int r,int D)
{
if(l>r) return 0;
int mid=l+r>>1, k=New_Node();
D_now=D, std::nth_element(p+l,p+mid,p+r+1,cmp);
t[k].pt=p[mid], Init(k);
t[k].ls=Build(l,mid-1,D^1), t[k].rs=Build(mid+1,r,D^1);
Update(k); return k;
}
void DFS(int rt,int num)
{
if(t[rt].ls) DFS(t[rt].ls,num);
p[num+t[t[rt].ls].sz+1]=t[rt].pt, sk[++top]=rt;
if(t[rt].rs) DFS(t[rt].rs,num+t[t[rt].ls].sz+1);
}
inline void Check(int &k,int D){
if(alpha*t[k].sz<t[t[k].ls].sz||alpha*t[k].sz<t[t[k].rs].sz)
DFS(k,0), k=Build(1,t[k].sz,D);
}
void Insert(Point p,int &k,int D)
{
if(!k) {t[k=New_Node()].pt=p, Init(k), t[k].sz=1, t[k].ls=t[k].rs=0; return;}
if(p.d[D]<=t[k].pt.d[D]) Insert(p,t[k].ls,D^1);
else Insert(p,t[k].rs,D^1);
Update(k), Check(k,D);
}
int Get_dis(Point p,int k)//Manhattan Distance
{
int res=0;
for(int i=0; i<2; ++i)
res+=std::max(0,p.d[i]-t[k].Max[i])+std::max(0,t[k].Min[i]-p.d[i]);
return res;
}
inline int Dis(Point a,Point b){
return std::abs(a.d[0]-b.d[0])+std::abs(a.d[1]-b.d[1]);
}
void Query(Point p,int k)//Manhattan Distance
{
Ans=std::min(Ans,Dis(t[k].pt,p));
int dl=t[k].ls?Get_dis(p,t[k].ls):INF;
int dr=t[k].rs?Get_dis(p,t[k].rs):INF;
if(dl<dr){
if(dl<Ans) Query(p,t[k].ls);
if(dr<Ans) Query(p,t[k].rs);
}
else{
if(dr<Ans) Query(p,t[k].rs);
if(dl<Ans) Query(p,t[k].ls);
}
} int main()
{
n=read(),Q=read();
for(int i=1; i<=n; ++i) p[i].d[0]=read(),p[i].d[1]=read();
root=Build(1,n,0); int x,y; Point tmp;
while(Q--)
if(read()==1) tmp.d[0]=read(),tmp.d[1]=read(),Insert(tmp,root,0);
else tmp.d[0]=read(),tmp.d[1]=read(),Ans=INF,Query(tmp,root),printf("%d\n",Ans); return 0;
}

2018.5.21 又写了遍,常数好像小了?(然并软)

//65280kb	14264ms(fread:65576kb	12412ms)
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define alpha (0.75)
const int N=5e5+5,INF=0x7fffffff; namespace KD_Tree
{
int n,Q,root,Now_d,top,sk[N<<1],Ans;
struct Point{
int d[2];
}p[N<<1];
struct Node{
int Min[2],Max[2],ls,rs,sz;
Point pt;
}t[N*3];//?? inline bool Cmp_d(const Point &a,const Point &b){
return a.d[Now_d]<b.d[Now_d];
}
inline int New_Node(){
return top?sk[top--]:++n;
}
inline void Init(int rt)
{
t[rt].sz=1;
for(int i=0; i<2; ++i)
t[rt].Min[i]=t[rt].Max[i]=t[rt].pt.d[i];
}
inline void Update(int rt)
{
int ls=t[rt].ls,rs=t[rt].rs;
t[rt].sz=t[ls].sz+t[rs].sz+1;
for(int i=0; i<2; ++i){
if(ls) t[rt].Min[i]=std::min(t[rt].Min[i],t[ls].Min[i]),t[rt].Max[i]=std::max(t[rt].Max[i],t[ls].Max[i]);
if(rs) t[rt].Min[i]=std::min(t[rt].Min[i],t[rs].Min[i]),t[rt].Max[i]=std::max(t[rt].Max[i],t[rs].Max[i]);
}
}
int Build(int l,int r,int D)
{
if(l>r) return 0;
int mid=l+r>>1,k=New_Node();
Now_d=D, std::nth_element(p+l,p+mid,p+r+1,Cmp_d);
t[k].pt=p[mid], Init(k);
t[k].ls=Build(l,mid-1,D^1), t[k].rs=Build(mid+1,r,D^1);
Update(k); return k;
}
void DFS(int rt,int num)
{
if(t[rt].ls) DFS(t[rt].ls,num);
p[num+t[t[rt].ls].sz+1]=t[rt].pt, sk[++top]=rt;
if(t[rt].rs) DFS(t[rt].rs,num+t[t[rt].ls].sz+1);
}
inline void Check(int &k,int D){
if(t[k].sz*alpha<t[t[k].ls].sz||t[k].sz*alpha<t[t[k].rs].sz)
DFS(k,0), k=Build(1,t[k].sz,D);
}
void Insert(Point p,int &k,int D)
{
if(!k) {t[k=New_Node()].pt=p, Init(k), t[k].ls=t[k].rs=0; return;}
if(p.d[D]<=t[k].pt.d[D]) Insert(p,t[k].ls,D^1);
else Insert(p,t[k].rs,D^1);
Update(k), Check(k,D);
}
int Dis_node(Point a,int k)
{
int res=0;
for(int i=0; i<2; ++i)
res+=std::max(0,a.d[i]-t[k].Max[i])+std::max(0,t[k].Min[i]-a.d[i]);
return res;
}
int Dis(Point a,Point b){
return std::abs(a.d[0]-b.d[0])+std::abs(a.d[1]-b.d[1]);
}
void Query(Point p,int k)
{
Ans=std::min(Ans,Dis(p,t[k].pt));
int dl=t[k].ls?Dis_node(p,t[k].ls):INF;
int dr=t[k].rs?Dis_node(p,t[k].rs):INF;
if(dl<dr){
if(dl<Ans) Query(p,t[k].ls);
if(dr<Ans) Query(p,t[k].rs);
}
else{
if(dr<Ans) Query(p,t[k].rs);
if(dl<Ans) Query(p,t[k].ls);
}
}
}
using namespace KD_Tree; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
} int main()
{
n=read(),Q=read();
for(int i=1; i<=n; ++i) p[i].d[0]=read(),p[i].d[1]=read();
root=Build(1,n,0); Point tmp;
while(Q--)
if(read()==1) tmp.d[0]=read(),tmp.d[1]=read(),Insert(tmp,root,0);
else tmp.d[0]=read(),tmp.d[1]=read(),Ans=INF,Query(tmp,root),printf("%d\n",Ans); return 0;
}

BZOJ.2716.[Violet3]天使玩偶(K-D Tree)的更多相关文章

  1. BZOJ.2716.[Violet3]天使玩偶(CDQ分治 坐标变换)

    题目链接 考虑对于两个点a,b,距离为|x[a]-x[b]|+|y[a]-y[b]|,如果a在b的右上,那我们可以把绝对值去掉,即x[a]+y[a]-(x[b]+y[b]). 即我们要求满足x[b]& ...

  2. BZOJ 2716: [Violet 3]天使玩偶

    2716: [Violet 3]天使玩偶 Time Limit: 80 Sec  Memory Limit: 128 MBSubmit: 1473  Solved: 621[Submit][Statu ...

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

    2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2459  Solved: 834[Submit][Status][Discu ...

  4. BZOJ 2716: [Violet 3]天使玩偶( CDQ分治 + 树状数组 )

    先cdq分治, 然后要处理点对答案的贡献, 可以以询问点为中心分成4个区域, 然后去掉绝对值(4种情况讨论), 用BIT维护就行了. --------------------------------- ...

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

    2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 Time Limit: 20 Sec  Memory Limit: 128 MB Description 这天,S ...

  6. 【bzoj 2716】[Violet 3]天使玩偶 (CDQ+树状数组)

    题目描述 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里,所以她决定仅凭一点模糊的记忆来寻找它. 我们把 Ayu 生活的 ...

  7. 【BZOJ】【2648】SJY摆棋子&【BZOJ】【2716】【Violet 3】天使玩偶

    KD-Tree 传说中的kd树...前去膜拜了一下……写道模板题>_< 写kdtree的一些感想: 插入的时候是像可持久化线段树一样直接在最后开新节点,然后更新它所在的块.. 然而其实也是 ...

  8. [bzoj] 2716 天使玩偶 || CDQ分治

    原题 已知n个点有天使玩偶,有m次操作: 操作1:想起来某个位置有一个天使玩偶 操作2:询问离当前点最近的天使玩偶的曼哈顿距离 显然的CDQ问题,三维分别为时间,x轴,y轴. 但是这道题的问题在于最近 ...

  9. BZOJ2648: SJY摆棋子&&2716: [Violet 3]天使玩偶

    BZOJ2648: SJY摆棋子 BZOJ2716: [Violet 3]天使玩偶 BZOJ氪金无极限... 其实这两道是同一题. 附上2648的题面: Description 这天,SJY显得无聊. ...

随机推荐

  1. vue-cli环境搭建初探!

    1.先安装nodejs环境 https://npm.taobao.org/mirrors/node (选择版本) 下一步 下一步 默认安装就行 2.检查node和npm的是否成功安装 node -v ...

  2. 【算法学习】【洛谷】树链剖分 & P3384 【模板】树链剖分 P2146 软件包管理器

    刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...

  3. Python标准库笔记(11) — Operator模块

    Operator--标准功能性操作符接口. 代码中使用迭代器时,有时必须要为一个简单表达式创建函数.有些情况这些函数可以用一个lambda函数实现,但是对于某些操作,根本没必要去写一个新的函数.因此o ...

  4. 【网页开发学习】Coursera课程《面向 Web 开发者的 HTML、CSS 与 Javascript》Week1课堂笔记

    Coursera课程<面向 Web 开发者的 HTML.CSS 与 Javascript> Johns Hopkins University Yaakov Chaikin Week1 In ...

  5. 读书笔记 effective c++ Item 28 不要返回指向对象内部数据(internals)的句柄(handles)

    假设你正在操作一个Rectangle类.每个矩形可以通过左上角的点和右下角的点来表示.为了保证一个Rectangle对象尽可能小,你可能决定不把定义矩形范围的点存储在Rectangle类中,而是把它放 ...

  6. const 和 #define区别_fenglovel_新浪博客

    const 和 #define区别 (2012-12-11 14:14:07) 转载▼ 标签: 杂谈   (1) 编译器处理方式不同 define宏是在预处理阶段展开. const常量是编译运行阶段使 ...

  7. C++之构造函数的继承

    #include<iostream> usingnamespace std; classBase1 { public: Base1()=default; Base1(const strin ...

  8. (四)Jsoup 获取 DOM 元素属性值

    第一节: Jsoup 获取 DOM 元素属性值 Jsoup获取DOM元素属性值 比如我们要获取博客的href属性值: 我们这时候就要用到Jsoup来获取属性的值 : 我们给下示例代码: package ...

  9. Asis CTF 2015-Car_Market

    恰好找到了这道题的bin文件,就来做一下. 这道题目是一个经典的选单程序但是具有三级选单,在bss段存在指针数组ptr,ptr中的值指向每个主结构,其中主结构如下所示. [] model [] pri ...

  10. GridView练习题

    package com.example.wang.myapplication; import android.os.Bundle; import android.support.v7.app.AppC ...