BZOJ_P2648
BZOJ_P2716
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 1980 Solved: 659
[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
Sample Output
1
2
HINT
kdtree可以过
Source
鸣谢 孙嘉裕
双倍经验,两道题一毛一样。
KD-Tree模板题
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 500005
#define INF 0x7fffffff
#define lc p[o].ch[0]
#define rc p[o].ch[1]
inline int in(int x=0,char ch=getchar(),int v=1){
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();if(ch=='-') v=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*v;}
struct Node{int d[2],mi[2],ma[2],ch[2];}p[N<<1],now;
int n,m,D,cnt,root,ans;
inline int cmp(Node a,Node b){return a.d[D]<b.d[D];}
inline void push_up(int o){
p[o].mi[0]=min(p[o].d[0],min(p[lc].mi[0],p[rc].mi[0]));
p[o].mi[1]=min(p[o].d[1],min(p[lc].mi[1],p[rc].mi[1]));
p[o].ma[0]=max(p[o].d[0],max(p[lc].ma[0],p[rc].ma[0]));
p[o].ma[1]=max(p[o].d[1],max(p[lc].ma[1],p[rc].ma[1]));
}
inline int dis(Node a,Node b){return fabs(a.d[0]-b.d[0])+fabs(a.d[1]-b.d[1]);}
void Build(int &o,int l,int r,int d){
D=d,o=(l+r)>>1;nth_element(p+l,p+o,p+r+1,cmp);
// for(int i=1;i<=n;i++) printf("%d %d\n",p[i].d[0],p[i].d[1]);
if(l<o) Build(lc,l,o-1,d^1);if(r>o) Build(rc,o+1,r,d^1);
push_up(o);
}
void insert(int &o,int d){
if(!o) o=++cnt,p[o]=now;
else if(now.d[d]<p[o].d[d]) insert(lc,d^1);
else insert(rc,d^1);
push_up(o);
}
int Calc(int o){
return max(p[o].mi[0]-now.d[0],0)+max(now.d[0]-p[o].ma[0],0)+
max(p[o].mi[1]-now.d[1],0)+max(now.d[1]-p[o].ma[1],0);
}
void Query(int o){
if(!o) return;
ans=min(ans,dis(p[o],now));
int ll=INF,rr=INF;
if(lc) ll=Calc(lc);if(rc) rr=Calc(rc);
if(ll<rr){
if(ll<ans) Query(lc);
if(rr<ans) Query(rc);
}
else{
if(rr<ans) Query(rc);
if(ll<ans) Query(lc);
}
}
int main(){
p[0].ma[0]=p[0].ma[1]=-INF;
p[0].mi[0]=p[0].mi[1]=INF;
cnt=n=in(),m=in();
for(int i=1;i<=n;i++) p[i].d[0]=in(),p[i].d[1]=in();
Build(root,1,n,0);int x;
while(m--){
x=in(),now.d[0]=in(),now.d[1]=in();
if(x==1) insert(root,0);
else ans=INF,Query(root),printf("%d\n",ans);
}
return 0;
}