首页 > 其他 > 详细

【bzoj2648】 SJY摆棋子

时间:2017-01-07 11:55:12      阅读:334      评论:0      收藏:0      [点我收藏+]

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/

细节

  码农数据结构题

代码

// bzoj2648
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 1<<30
#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,maxm=2;
int n,rt,K,ans,m;

struct KDtree {
	int v[maxm],mn[maxm],mx[maxm],l,r;
	friend bool operator < (const KDtree a,const KDtree b) {
		return a.v[K]<b.v[K];
	}
}tr[maxn],S;

void update(int k) {
	if (tr[k].l)
		for (int i=0;i<=1;i++) {
			tr[k].mx[i]=max(tr[k].mx[i],tr[tr[k].l].mx[i]);
			tr[k].mn[i]=min(tr[k].mn[i],tr[tr[k].l].mn[i]);
		}
	if (tr[k].r)
		for (int i=0;i<=1;i++) {
			tr[k].mx[i]=max(tr[k].mx[i],tr[tr[k].r].mx[i]);
			tr[k].mn[i]=min(tr[k].mn[i],tr[tr[k].r].mn[i]);
		}
}
int dis(KDtree a,KDtree b) {
	int res=0;
	for (int i=0;i<=1;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<=1;i++) res+=max(0,tr[k].mn[i]-S.v[i])+max(0,S.v[i]-tr[k].mx[i]);   //画个图YY一下,很有道理
	return res;
}
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<=1;i++) tr[mid].mn[i]=tr[mid].mx[i]=tr[mid].v[i];
	if (l<mid) tr[mid].l=build(l,mid-1,p^1);
	if (r>mid) tr[mid].r=build(mid+1,r,p^1);
	update(mid);
	return mid;
}
void insert(int k,int p) {
	K=p;
	if (S<tr[k]) {
		if (tr[k].l) insert(tr[k].l,p^1);
		else {
			tr[k].l=++n;tr[n]=S;
			for (int i=0;i<=1;i++) tr[n].mx[i]=tr[n].mn[i]=tr[n].v[i];
		}
	}
	else {
		if (tr[k].r) insert(tr[k].r,p^1);
		else {
			tr[k].r=++n;tr[n]=S;
			for (int i=0;i<=1;i++) tr[n].mx[i]=tr[n].mn[i]=tr[n].v[i];
		}
	}
	update(k);
}
void query(int k) {
	ans=min(ans,dis(S,tr[k]));   //更新答案
	int dl=eva(tr[k].l),dr=eva(tr[k].r);
	if (dl<dr) {
		if (dl<ans) query(tr[k].l);
		if (dr<ans) query(tr[k].r);
	}
	else {
		if (dr<ans) query(tr[k].r);
		if (dl<ans) query(tr[k].l);
	}
}
	
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;
}

 

【bzoj2648】 SJY摆棋子

原文:http://www.cnblogs.com/MashiroSky/p/6258825.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!