传送门
这道题和BZOJ2716一样:http://blog.csdn.net/qq_35649707/article/details/77800032
不过CDQ过不了。。。
于是写了KD树。。其实就是一个玄学DFS减枝。
表示写了一个替罪羊树套在里面还变慢了。。
#include<bits/stdc++.h>
using namespace std;
struct IO{
streambuf *ib,*ob;
inline void init(){
ios::sync_with_stdio(false);
cin.tie(NULL),cout.tie(NULL);
ib=cin.rdbuf();ob=cout.rdbuf();
}
inline int read(){
char ch=ib->sbumpc();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}
return i*f;
}
inline void W(int x){
static int buf[50];
if(!x){ob->sputc('0');ob->sputc('\n');return;}
if(x<0){ob->sputc('-');x=-x;}
while(x){buf[++buf[0]]=x%10;x/=10;}
while(buf[0])
{ob->sputc(buf[buf[0]--]+'0');}
ob->sputc('\n');
}
}io;
const int INF=0x3f3f3f3f;
const int Maxn=1e6+50;
int n,m;
struct point{
int x[2];
point(int x=0,int y=0){
this->x[0]=x;this->x[1]=y;
}
inline int dist(point p){
return abs(p.x[0]-this->x[0])+abs(p.x[1]-this->x[1]);
}
}pp[Maxn];
inline bool cmp0(const point &a,const point &b){
return a.x[0]<b.x[0];
}
inline bool cmp1(const point &a,const point &b){
return a.x[1]<b.x[1];
}
struct node{
node *c[2];
point p;
int mx[2],mn[2];
inline void upt(node *c);
}Pool[Maxn],*pool=Pool,*null=pool;
inline node* newnode(point p){
++pool;
pool->c[0]=pool->c[1]=null;
pool->p=p;
pool->mx[0]=pool->mn[0]=p.x[0];
pool->mx[1]=pool->mn[1]=p.x[1];
return pool;
}
void node::upt(node *c){
mx[0]=max(mx[0],c->mx[0]);mn[0]=min(mn[0],c->mn[0]);
mx[1]=max(mx[1],c->mx[1]);mn[1]=min(mn[1],c->mn[1]);
}
struct KDimTree{
node *rt;
KDimTree():rt(null){}
inline void insert(node*& now,int dim,point p){
if(now==null){now=newnode(p);return;}
if(p.x[dim]<now->p.x[dim])insert(now->c[0],dim^1,p),now->upt(now->c[0]);
else insert(now->c[1],dim^1,p),now->upt(now->c[1]);
}
inline int mindist(node *now,point p){
if(now==null)return INF;
int res=0;
for(int i=0;i<2;i++){
if(now->mn[i]>p.x[i])res+=now->mn[i]-p.x[i];
else if(now->mx[i]<p.x[i])res+=p.x[i]-now->mx[i];
}
return res;
}
inline void query(node* now,point p,int &ans){
if(now==null)return;
ans=min(ans,p.dist(now->p));
int dl=mindist(now->c[0],p),dr=mindist(now->c[1],p);
if(dl<dr){
if(dl<ans)query(now->c[0],p,ans);
if(dr<ans)query(now->c[1],p,ans);
}
else{
if(dr<ans)query(now->c[1],p,ans);
if(dl<ans)query(now->c[0],p,ans);
}
}
inline void build(node*& now,point* p,int l,int r,int dim){
int mid=(l+r)>>1;
if(dim)nth_element(p+l,p+mid,p+r+1,cmp1);
else nth_element(p+l,p+mid,p+r+1,cmp0);
now=newnode(p[mid]);
if(l==r)return;
if(l<mid)build(now->c[0],p,l,mid-1,dim^1),now->upt(now->c[0]);
if(mid<r)build(now->c[1],p,mid+1,r,dim^1),now->upt(now->c[1]);
}
}kdtree;
int main(){
io.init();n=io.read(),m=io.read();
for(int i=1;i<=n;i++){
pp[i].x[0]=io.read(),pp[i].x[1]=io.read();
}
kdtree.build(kdtree.rt,pp,1,n,0);
for(int i=1;i<=m;i++){
int op=io.read(),x=io.read(),y=io.read();
if(op==1){
kdtree.insert(kdtree.rt,0,point(x,y));
}
else{
int ans=INF;
kdtree.query(kdtree.rt,point(x,y),ans);
io.W(ans);
}
}
}
#include<bits/stdc++.h>
using namespace std;
struct IO{
streambuf *ib,*ob;
inline void init(){
ios::sync_with_stdio(false);
cin.tie(NULL),cout.tie(NULL);
ib=cin.rdbuf();ob=cout.rdbuf();
}
inline int read(){
char ch=ib->sbumpc();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}
return i*f;
}
inline void W(int x){
static int buf[50];
if(!x){ob->sputc('0');ob->sputc('\n');return;}
if(x<0){ob->sputc('-');x=-x;}
while(x){buf[++buf[0]]=x%10;x/=10;}
while(buf[0])
{ob->sputc(buf[buf[0]--]+'0');}
ob->sputc('\n');
}
}io;
const int INF=0x3f3f3f3f;
const int Maxn=1e6+50;
int n,m;
struct point{
int x[2];
point(int x=0,int y=0){
this->x[0]=x;this->x[1]=y;
}
inline int dist(point p){
return abs(p.x[0]-this->x[0])+abs(p.x[1]-this->x[1]);
}
}pp[Maxn];
inline bool cmp0(const point &a,const point &b){
return a.x[0]<b.x[0];
}
inline bool cmp1(const point &a,const point &b){
return a.x[1]<b.x[1];
}
struct node{
node *c[2];
point p;
int mx[2],mn[2],sze,nowdim;
inline void upt();
}Pool[Maxn],*pool=Pool,*null=pool,*recyclepool[Maxn];
int pooltail;
inline node* newnode(point p){
node *tmp=(pooltail==0)?(++pool):(recyclepool[pooltail--]);
tmp->c[0]=tmp->c[1]=null;
tmp->p=p;tmp->sze=1;
tmp->mx[0]=tmp->mn[0]=p.x[0];
tmp->mx[1]=tmp->mn[1]=p.x[1];
return tmp;
}
void node::upt(){
sze=1;
for(int i=0;i<2;i++){
if(c[i]==null)continue;
mx[0]=max(mx[0],c[i]->mx[0]);mn[0]=min(mn[0],c[i]->mn[0]);
mx[1]=max(mx[1],c[i]->mx[1]);mn[1]=min(mn[1],c[i]->mn[1]);
sze+=c[i]->sze;
}
}
const int alpha=78;
struct KDimTree{
node *rt;
KDimTree():rt(null){}
inline void insert(node*& now,int dim,point p,node**& o){
if(now==null){now=newnode(p);now->nowdim=dim;return;}
if(p.x[dim]<now->p.x[dim])insert(now->c[0],dim^1,p,o);
else insert(now->c[1],dim^1,p,o);
now->upt();
if(now->c[0]->sze*100>now->sze*alpha||now->c[1]->sze*100>now->sze*alpha)o=&now;
}
inline int mindist(node *now,point p){
if(now==null)return INF;
int res=0;
for(int i=0;i<2;i++){
if(now->mn[i]>p.x[i])res+=now->mn[i]-p.x[i];
else if(now->mx[i]<p.x[i])res+=p.x[i]-now->mx[i];
}
return res;
}
inline void query(node* now,point p,int &ans){
if(now==null)return;
ans=min(ans,p.dist(now->p));
int dl=mindist(now->c[0],p),dr=mindist(now->c[1],p);
if(dl<dr){
if(dl<ans)query(now->c[0],p,ans);
if(dr<ans)query(now->c[1],p,ans);
}
else{
if(dr<ans)query(now->c[1],p,ans);
if(dl<ans)query(now->c[0],p,ans);
}
}
inline void build(node*& now,point* p,int l,int r,int dim){
int mid=(l+r)>>1;
if(dim)nth_element(p+l,p+mid,p+r+1,cmp1);
else nth_element(p+l,p+mid,p+r+1,cmp0);
now=newnode(p[mid]);
now->nowdim=dim;
if(l==r)return;
if(l<mid)build(now->c[0],p,l,mid-1,dim^1);
if(mid<r)build(now->c[1],p,mid+1,r,dim^1);
now->upt();
}
inline void travel(node *now,int &tail){
if(now==null)return;
travel(now->c[0],tail);
pp[++tail]=now->p;recyclepool[++pooltail]=now;
travel(now->c[1],tail);
now=null;
}
inline void rebuild(node *&now){
static int tail;
tail=0;
int dim=now->nowdim;
travel(now,tail);
build(now,pp,1,tail,dim);
}
}kdtree;
int main(){
io.init();n=io.read(),m=io.read();
for(int i=1;i<=n;i++){
pp[i].x[0]=io.read(),pp[i].x[1]=io.read();
}
kdtree.build(kdtree.rt,pp,1,n,0);
for(int i=1;i<=m;i++){
int op=io.read(),x=io.read(),y=io.read();
if(op==1){
node ** o=&null;
kdtree.insert(kdtree.rt,0,point(x,y),o);
if(*o!=null)kdtree.rebuild(*o);
}
else{
int ans=INF;
kdtree.query(kdtree.rt,point(x,y),ans);
io.W(ans);
}
}
}