http://www.lydsy.com/JudgeOnline/problem.php?id=2648 (题目链接)

题意

  动态维护二维平面上的点的插入以及最邻近域搜索。

Solution

  KDtree板子,代码膜的XlightGod。复杂度真的萎,感觉主要还是剪枝。

  理论:http://blog.csdn.net/silangquan/article/details/41483689

  实现:http://blog.xlightgod.com/%E3%80%90bzoj2648%E3%80%91sjy%E6%91%86%E6%A3%8B%E5%AD%90/

细节

  码农数据结构题

代码

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=1000010;
int n,rt,K,m,ans; struct node {
int v[2],mn[2],mx[2],son[2];
friend bool operator < (const node &a,const node &b) {return a.v[K]<b.v[K];}
int& operator [] (int x) {return son[x];}
}tr[maxn],S; void pushup(int k) {
for (int i=0;i<2;i++) {
if (!tr[k][i]) continue;
for (int j=0;j<2;j++) {
tr[k].mx[j]=max(tr[k].mx[j],tr[tr[k][i]].mx[j]);
tr[k].mn[j]=min(tr[k].mn[j],tr[tr[k][i]].mn[j]);
}
}
}
int build(int l,int r,int p) {
K=p;int mid=(l+r)>>1;
nth_element(tr+l,tr+mid,tr+r+1); //闭,闭,开
for (int i=0;i<2;i++) tr[mid].mn[i]=tr[mid].mx[i]=tr[mid].v[i];
if (l<mid) tr[mid][0]=build(l,mid-1,p^1);
if (r>mid) tr[mid][1]=build(mid+1,r,p^1);
pushup(mid);
return mid;
}
void insert(int &k,int p) {
K=p;
if (!k) {
k=++n;tr[k]=S;
for (int i=0;i<2;i++) tr[k].mx[i]=tr[k].mn[i]=tr[k].v[i];
return;
}
else insert(tr[k][S<tr[k]],p^1);
pushup(k);
}
int dis(node a,node b) {
int res=0;
for (int i=0;i<2;i++) res+=abs(a.v[i]-b.v[i]);
return res;
}
int eva(int k) { //类似估价函数
if (!k) return inf;
int res=0;
for (int i=0;i<2;i++) res+=max(0,tr[k].mn[i]-S.v[i])+max(0,S.v[i]-tr[k].mx[i]);
return res;
}
void query(int k) {
ans=min(ans,dis(S,tr[k]));
int dl=eva(tr[k][0]),dr=eva(tr[k][1]);
if (dl<dr) {
if (dl<ans) query(tr[k][0]);
if (dr<ans) query(tr[k][1]);
}
else {
if (dr<ans) query(tr[k][1]);
if (dl<ans) query(tr[k][0]);
}
}
int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d%d",&tr[i].v[0],&tr[i].v[1]);
rt=build(1,n,0);
for (int op,i=1;i<=m;i++) {
scanf("%d%d%d",&op,&S.v[0],&S.v[1]);
if (op==1) insert(rt,0);
else {
ans=inf;
query(rt);
printf("%d\n",ans);
}
}
return 0;
}

Solution

  CDQ分治。考虑在查询点左下方的点里面$|x+y|$最大的,这个每次CDQ分治的时候按照x排序然后树状数组维护一下就可以了。然后我们将坐标轴旋转一下,做4个方向,然后就搞完了。

  TTTTTLE,过不了了,也许你需要底层优化。

细节

  清空的时候注意复杂度。

代码

// bzoj2648
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 2147483600
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std;
inline int gi() {
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;
} const int maxn=1000010;
int n,m,X,Y,c[maxn];
struct data {int x,y,id,op,ans;}q[maxn],nq[maxn]; bool cmp(data a,data b) {return a.x<b.x;}
bool cmpid(data a,data b) {return a.id<b.id;}
int lowbit(int x) {
return x&-x;
}
void modify(int x,int val) {
for (int i=x;i<=Y;i+=lowbit(i)) c[i]=max(c[i],val);
}
void clear(int x) {
for (int i=x;i<=Y;i+=lowbit(i)) c[i]=-inf;
}
int query(int x) {
int res=-inf;
for (int i=x;i;i-=lowbit(i)) res=max(res,c[i]);
return res;
}
void solve(int l,int r) {
if (l==r) return;
int mid=(l+r)>>1,l1=l,l2=mid+1;
for (int i=l;i<=r;i++) q[i].id<=mid ? nq[l1++]=q[i] : nq[l2++]=q[i];
for (int i=l;i<=r;i++) q[i]=nq[i];
for (int i=l,j=mid+1;i<=mid || j<=r;) {
if (j>r || (i<=mid && q[i].x<=q[j].x)) {
if (q[i].op==1) modify(q[i].y,q[i].x+q[i].y);
i++;
}
else {
if (q[j].op==2) q[j].ans=min(q[j].ans,abs(q[j].x+q[j].y-query(q[j].y)));
j++;
}
}
for (int i=l;i<=mid;i++) if (q[i].op==1) clear(q[i].y);
solve(l,mid);solve(mid+1,r);
}
int main() {
scanf("%d%d",&n,&m);X=-inf,Y=-inf;
for (int i=1;i<=n;i++) {
q[i].x=gi()+1,q[i].y=gi()+1;
X=max(q[i].x,X);Y=max(q[i].y,Y);
q[i].id=i,q[i].op=1;q[i].ans=inf;
}
for (int i=1;i<=m;i++) {
q[i+n].op=gi(),q[i+n].x=gi()+1,q[i+n].y=gi()+1;
X=max(q[i+n].x,X);Y=max(q[i+n].y,Y);
q[i+n].id=i+n;q[i+n].ans=inf;
}
n+=m;
for (int i=1;i<=n;i++) c[i]=-inf;
sort(q+1,q+1+n,cmp);solve(1,n);
for (int i=1;i<=n;i++) q[i].x=X-q[i].x+1;
sort(q+1,q+1+n,cmp);solve(1,n);
for (int i=1;i<=n;i++) q[i].y=Y-q[i].y+1;
sort(q+1,q+1+n,cmp);solve(1,n);
for (int i=1;i<=n;i++) q[i].x=X-q[i].x+1;
sort(q+1,q+1+n,cmp);solve(1,n);
for (int i=1;i<=n;i++) if (q[i].ans!=inf) printf("%d\n",q[i].ans);
return 0;
}

【bzoj2648】 SJY摆棋子的更多相关文章

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

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

  2. [BZOJ2648] SJY摆棋子 kd-tree

    2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 5421  Solved: 1910[Submit][Status][Disc ...

  3. Bzoj2648 SJY摆棋子

    Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 3128  Solved: 1067 Description 这天,SJY显得无聊.在家自己玩.在一个 ...

  4. BZOJ2648 SJY摆棋子(KD-Tree)

    板子题. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> # ...

  5. 【kd-tree】bzoj2648 SJY摆棋子

    #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define ...

  6. 2019.01.14 bzoj2648: SJY摆棋子(kd-tree)

    传送门 kd−treekd-treekd−tree模板题. 题意简述:支持在平面上插入一个点,求对于一个点的最近点对. 思路:cdqcdqcdq是一种很不错的分治方法 只是好像码量有点窒息 所以我用了 ...

  7. KDTree(Bzoj2648: SJY摆棋子)

    题面 传送门 KDTree 大概就是一个分割\(k\)维空间的数据结构,二叉树 建立:每层选取一维为关键字,把中间的点拿出来,递归左右,有个\(STL\)函数nth_element可以用一下 维护:维 ...

  8. [bzoj2648]SJY摆棋子(带插入kd-tree)

    解题关键:带插入kdtree模板题. #include<iostream> #include<cstdio> #include<cstring> #include& ...

  9. luogu4169 [Violet]天使玩偶/SJY摆棋子 / bzoj2648 SJY摆棋子 k-d tree

    k-d tree + 重构的思想,就能卡过luogu和bzoj啦orz #include <algorithm> #include <iostream> #include &l ...

  10. 【BZOJ2648】SJY摆棋子(KD-Tree)

    [BZOJ2648]SJY摆棋子(KD-Tree) 题面 BZOJ Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一 ...

随机推荐

  1. 开始我的IT博客之旅

    这是一个好的开始,过程很漫长,但我却乐在其中. 在大学之际,这是我的又一个开始,随便写点啦. 想把每一次的过程记录下来 这样以后对自己 对别人都会有所帮助. 好啦 作为一名大三的学生党  加油吧!

  2. Spring in Action 学习笔记二-DI

    装配bean 2015年10月9日 9:49             Sprng中,对象无需自己负责查找或创建其关联的其他对象.相关,容器负责吧需要相互协作的对象引用赋予各个对象. 创建应用对象之间协 ...

  3. iOS获取app图标和启动图片名字(AppIcon and LaunchImage's name)

    在某种场景下,可能我们需要获取app的图标名称和启动图片的名称.比如说app在前台时,收到了远程通知但是通知栏是不会有通知提醒的,这时我想做个模拟通知提示,需要用到icon名称:再比如在加载某个控制器 ...

  4. xamarin 一般错误解决办法

    1. android_m2repository_r错误 问题描述: Unzipping failed. Please download https://dl-ssl.google.com/androi ...

  5. Android 多个listview的实现

    正好,今天项目中需要,先写了个demo,给大家参考参考. 先上图,需要的自己,看看具体的代码实现步骤 大概说一下实现步骤: 1.布局中先用 scrollview 包裹 LinearLayout < ...

  6. 使用Fiddler抓取手机请求

    使用Fiddler抓取手机请求 Fiddler 手机 今天想尝试在手机上抓包,发现一个好玩的小工具——Fiddler. Fiddler是一个专门的抓包工具,可以模拟请求,修改请求,手机应用调试等.还是 ...

  7. 记录一次Quartz2D学习(三)

    在(二)内,讲到了几何图形的绘制,这次就讲文本与图片的绘制 3 图片与文本 3.1 文本绘制 - (void)drawRect:(CGRect)rect { NSString * str = @&qu ...

  8. solr定时更新索引遇到的问题(SolrDataImportProperties Error loading DataImportScheduler properties java.lang.NullPointerException)

    问题描述 报如下错误,很显然,问题原因:空指针异常: ERROR (localhost-startStop-1) [   ] o.a.s.h.d.s.SolrDataImportProperties ...

  9. 首页大图淡入淡出效果工具flexslider

    网站首页放几张高清大图轮流播放展示是目首页设计的流行做法,虽然woothemes.com已经公布了比较成熟的flexslider工具,但本着造轮子的心态,我也做了一个自己的flexslider,当然我 ...

  10. Vmware虚拟机Devstack安装openstack(All in one)

    Vmware虚拟机Devstack安装openstack(All in one) 博客园第一篇博客,先练习一下. 官方文档 环境 Vmware虚拟机 OS : Ubuntu 14.04 Nat网络,D ...