bzoj2648 SJY摆棋子
Posted wzjhoutai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2648 SJY摆棋子相关的知识,希望对你有一定的参考价值。
2648: SJY摆棋子
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1821 Solved: 591
[Submit][Status][Discuss]
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
1 1
2 3
2 1 2
1 3 3
2 4 2
Sample Output
1
2
HINT
kdtree能够过
Source
K-D Tree第一题。唉,人生若仅仅如初见......
这道题考察的是K-D Tree在近期邻搜索方面的应用。非常显然,对于黑棋。增加到K-D Tree里。对于白棋,询问近期邻。
以下写一些自己关于这道题的理解吧:
1.K-D Tree本质上是一种DFS的剪枝优化。
2.每一层相应的区分维度是循环的。
因为这道题仅仅有两维,所以能够利用位运算的异或操作。
3.在每一层的DFS中。有一个get函数,相当于预计了子区域距离那个点近期是多少,注意是预计。下一次的DFS就从dl和dr中较小的一边開始。感觉方法还是非常巧妙的。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define maxn 500005 #define inf 1000000000 using namespace std; int n,m,root,D,ans; struct data { int d[2],mn[2],mx[2],l,r; }p[maxn],t[maxn*2],tmp; bool operator<(data a,data b) { return a.d[D]<b.d[D]; } 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; } inline int dis(data a,data b) { return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]); } inline void pushup(int k) { int ls=t[k].l,rs=t[k].r; F(i,0,1) { if (ls) { t[k].mn[i]=min(t[k].mn[i],t[ls].mn[i]); t[k].mx[i]=max(t[k].mx[i],t[ls].mx[i]); } if (rs) { t[k].mn[i]=min(t[k].mn[i],t[rs].mn[i]); t[k].mx[i]=max(t[k].mx[i],t[rs].mx[i]); } } } inline int build(int l,int r,int now) { D=now; int mid=(l+r)>>1; nth_element(p+l,p+mid,p+r+1); t[mid]=p[mid]; F(i,0,1) t[mid].mn[i]=t[mid].mx[i]=t[mid].d[i]; if (l<mid) t[mid].l=build(l,mid-1,now^1); if (mid<r) t[mid].r=build(mid+1,r,now^1); pushup(mid); return mid; } inline int get(int k,data x) { int tmp=0; F(i,0,1) tmp+=max(0,t[k].mn[i]-x.d[i]); F(i,0,1) tmp+=max(0,x.d[i]-t[k].mx[i]); return tmp; } inline void insert(int k,int now) { if (tmp.d[now]>=t[k].d[now]) { if (t[k].r) insert(t[k].r,now^1); else { t[k].r=++n;t[n]=tmp; F(i,0,1) t[n].mn[i]=t[n].mx[i]=t[n].d[i]; } } else { if (t[k].l) insert(t[k].l,now^1); else { t[k].l=++n;t[n]=tmp; F(i,0,1) t[n].mn[i]=t[n].mx[i]=t[n].d[i]; } } pushup(k); } inline void query(int k,int now) { int d,dl=inf,dr=inf; d=dis(t[k],tmp); ans=min(ans,d); if (t[k].l) dl=get(t[k].l,tmp); if (t[k].r) dr=get(t[k].r,tmp); if (dl<dr) { if (dl<ans) query(t[k].l,now^1); if (dr<ans) query(t[k].r,now^1); } else { if (dr<ans) query(t[k].r,now^1); if (dl<ans) query(t[k].l,now^1); } } int main() { n=read();m=read(); F(i,1,n){p[i].l=p[i].r=0;p[i].d[0]=read();p[i].d[1]=read();} root=build(1,n,0); tmp.l=tmp.r=0; while (m--) { int opt=read();tmp.d[0]=read();tmp.d[1]=read(); if (opt==1) insert(root,0); else { ans=inf; query(root,0); printf("%d\n",ans); } } return 0; }
以上是关于bzoj2648 SJY摆棋子的主要内容,如果未能解决你的问题,请参考以下文章