Description
为了写论文,Alex经常要整理大量的数据。 这一次,Alex面临一个严峻的考验:他需要实现一个数据结构来维护一个点集。
现在,二维平面上有N个点。Alex 需要实现以下三种操作:
1. 在点集里添加一个点;
2. 给出一个点,查询它到点集里所有点的曼哈顿距离的最小值;
3. 给出一个点,查询它到点集里所有点的曼哈顿距离的最大值。
两个点的曼哈顿距离定义为它们的横坐标差的绝对值与纵坐标差的绝对值的和。这么困难的问题,Alex当然不会做,只好再次请你帮忙了。
Input
第一行包含一个整数N,表示点集最初的点数。
接下来N行,每行两个整数,依次表示每个点的横坐标和纵坐标。
第N+2行包含一个整数Q,表示询问的数目。
接下来Q行,每行三个整数,依次表示询问的类型,点的横坐标和纵坐标。0类型表示添加一个点,1类型表示查询到该点的曼哈顿距离的最小值,2类型表示查询最大值。
1 ≤ N, Q ≤ 100,000,点的坐标是不超过10^8的非负整数
Output
输出若干行,依次表示每个查询操作的答案。
Sample Input
3
7 5
6 2
3 1
5
1 6 1
1 5 5
2 7 1
0 3 2
1 1 0
7 5
6 2
3 1
5
1 6 1
1 5 5
2 7 1
0 3 2
1 1 0
Sample Output
1
2
4
3
2
4
3
两年前,这道题对于我还是只能仰视的存在,犹记得当时被标算的CDQ分治D飞。
今天,它成为了kd树模板题。
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<algorithm> #define L T[o].lc #define R T[o].rc #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ren for(int i=first[x];i;i=next[i]) using namespace std; const int BufferSize=1<<16; char buffer[BufferSize],*head,*tail; inline char Getchar() { if(head==tail) { int l=fread(buffer,1,BufferSize,stdin); tail=(head=buffer)+l; } return *head++; } inline int read() { int x=0,f=1;char c=Getchar(); for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1; for(;isdigit(c);c=Getchar()) x=x*10+c-'0'; return x*f; } const int maxn=200010; const int inf=1e9; int D,ToT; struct Node { int x[2],mx[2],mn[2]; int lc,rc; bool operator < (const Node& ths) const {return x[D]<ths.x[D];} }T[maxn]; void maintain(int o) { rep(i,0,1) T[o].mx[i]=max(T[o].x[i],max(T[L].mx[i],T[R].mx[i])),T[o].mn[i]=min(T[o].x[i],min(T[L].mn[i],T[R].mn[i])); } void build(int& o,int l,int r,int c) { if(l>r) return;int mid=l+r>>1;D=c;o=mid; nth_element(T+l,T+mid,T+r+1); build(L,l,mid-1,c^1);build(R,mid+1,r,c^1); maintain(o); } Node x; void insert(int& o,int c) { if(!o) o=++ToT,T[o]=x; else insert(x.x[c]<=T[o].x[c]?L:R,c^1); maintain(o); } int ans; int dist(Node& a,Node& b) {return abs(a.x[0]-b.x[0])+abs(a.x[1]-b.x[1]);} int calmn(int o) { int res=0; if(x.x[0]<T[o].mn[0]) res+=T[o].mn[0]-x.x[0]; if(x.x[0]>T[o].mx[0]) res+=x.x[0]-T[o].mx[0]; if(x.x[1]<T[o].mn[1]) res+=T[o].mn[1]-x.x[1]; if(x.x[1]>T[o].mx[1]) res+=x.x[1]-T[o].mx[1]; return res; } int calmx(int o) {return max(abs(x.x[0]-T[o].mx[0]),abs(x.x[0]-T[o].mn[0]))+max(abs(x.x[1]-T[o].mx[1]),abs(x.x[1]-T[o].mn[1]));} void querymn(int o) { if(!o) return; ans=min(ans,dist(T[o],x)); int dl=calmn(L),dr=calmn(R); if(dl<dr) { if(dl<ans) querymn(L); if(dr<ans) querymn(R); } else { if(dr<ans) querymn(R); if(dl<ans) querymn(L); } } void querymx(int o) { if(!o) return; ans=max(ans,dist(T[o],x)); int dl=calmx(L),dr=calmx(R); if(dl>dr) { if(dl>ans) querymx(L); if(dr>ans) querymx(R); } else { if(dr>ans) querymx(R); if(dl>ans) querymx(L); } } int main() { T[0].mx[0]=T[0].mx[1]=-inf; T[0].mn[0]=T[0].mn[1]=inf; int n=read(),rt=0;ToT=n; rep(i,1,n) T[i].x[0]=read(),T[i].x[1]=read(); build(rt,1,n,0); dwn(i,read(),1) { int t=read();x.x[0]=read();x.x[1]=read(); if(!t) insert(rt,0); else if(t==1) ans=inf,querymn(rt); else ans=-inf,querymx(rt); if(t) printf("%d ",ans); } return 0; }