P4169 [Violet]天使玩偶/SJY摆棋子

传送门

用kdtree重新写了一遍
然后发现kdtree竟然跑的比CDQ快?
也是很神奇了……

//minamoto
#include<bits/stdc++.h>
#define R register
#define inf 0x3f3f3f3f
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
    if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e6+5;const double alph=0.75;
struct point{int x[2];}p[N];
struct node{int mn[2],mx[2],ls,rs,sz;point tp;}tr[N];
int n,m,rt,cur,top,WD,ans,st[N];
inline bool operator <(point a,point b){return a.x[WD]<b.x[WD];}
inline int newnode(){return top?st[top--]:++cur;}
void upd(int p){
	int l=tr[p].ls,r=tr[p].rs;
	fp(i,0,1){
		tr[p].mn[i]=tr[p].mx[i]=tr[p].tp.x[i];
		if(l)cmin(tr[p].mn[i],tr[l].mn[i]),cmax(tr[p].mx[i],tr[l].mx[i]);
		if(r)cmin(tr[p].mn[i],tr[r].mn[i]),cmax(tr[p].mx[i],tr[r].mx[i]);
	}tr[p].sz=tr[l].sz+tr[r].sz+1;
}
int build(int l,int r,int wd){
	if(l>r)return 0;int k=newnode(),mid=(l+r)>>1;
	WD=wd,nth_element(p+l,p+mid,p+r+1),tr[k].tp=p[mid];
	tr[k].ls=build(l,mid-1,wd^1),tr[k].rs=build(mid+1,r,wd^1);
	upd(k);return k;
}
void pia(int k,int sum){
	if(tr[k].ls)pia(tr[k].ls,sum);
	p[sum+tr[tr[k].ls].sz+1]=tr[k].tp,st[++top]=k;
	if(tr[k].rs)pia(tr[k].rs,sum+tr[tr[k].ls].sz+1);
}
void check(int &p,int wd){
	if(alph*tr[p].sz<tr[tr[p].ls].sz||alph*tr[p].sz<tr[tr[p].rs].sz)
	pia(p,0),p=build(1,tr[p].sz,wd);
}
void ins(point res,int &p,int wd){
	if(!p)return (void)(p=newnode(),tr[p].tp=res,tr[p].ls=tr[p].rs=0,upd(p));
	if(tr[p].tp.x[wd]<res.x[wd])ins(res,tr[p].rs,wd^1);
	else ins(res,tr[p].ls,wd^1);upd(p),check(p,wd);
}
int getdis(point res,int p){
	int r=0;fp(i,0,1)r+=max(0,res.x[i]-tr[p].mx[i])+max(0,tr[p].mn[i]-res.x[i]);
	return r;
}
int dis(point a,point b){return abs(a.x[0]-b.x[0])+abs(a.x[1]-b.x[1]);}
void query(point res,int p){
	cmin(ans,dis(res,tr[p].tp));
	int dl=inf,dr=inf;
	if(tr[p].ls)dl=getdis(res,tr[p].ls);
	if(tr[p].rs)dr=getdis(res,tr[p].rs);
	if(dl<dr){
		if(dl<ans)query(res,tr[p].ls);
		if(dr<ans)query(res,tr[p].rs);
	}else{
		if(dr<ans)query(res,tr[p].rs);
		if(dl<ans)query(res,tr[p].ls);
	}
}
int main(){
//	freopen("testdata.in","r",stdin);
	n=read(),m=read();
	fp(i,1,n)p[i].x[0]=read(),p[i].x[1]=read();
	rt=build(1,n,0);
	while(m--){
		point res;int op=read();res.x[0]=read(),res.x[1]=read();
		if(op==1)ins(res,rt,0);
		else ans=inf,query(res,rt),print(ans);
	}return Ot(),0;
}
posted @ 2018-12-07 21:05  bztMinamoto  阅读(254)  评论(0编辑  收藏  举报
Live2D