您的位置:首页 > 其它

[BZOJ2648]=[BZOJ2716]SJY摆棋子

2016-02-23 23:41 363 查看
原题地址

Kdtree的带插入最邻近点查询.

轮流划分维度+暴力插入AC了,而且时间排名还比较靠前…

AC code:

#include <cstdio>
#include <algorithm>
using namespace std;
const int K=2;
const int N=1000010;
const int INF=1<<29;
int n,m,mn,tot,flg;

struct Poi{
int d[K];

Poi() {}
Poi(int x,int y) {d[0]=x;d[1]=y;}

friend bool operator<(Poi x,Poi y){
return x.d[flg]<y.d[flg];
}
}a
;

struct nod{
Poi poi;
int mxd[K],mnd[K];
nod *ch[2];
}pool
;

struct Kdtree{
nod *root;

Kdtree(){
build(&root,1,n,0);
}

void update(nod *p){
for(int i=0;i<K;i++){
p->mxd[i]=p->mnd[i]=p->poi.d[i];
if(p->ch[0]!=NULL){
p->mxd[i]=max(p->mxd[i],p->ch[0]->mxd[i]);
p->mnd[i]=min(p->mnd[i],p->ch[0]->mnd[i]);
}
if(p->ch[1]!=NULL){
p->mxd[i]=max(p->mxd[i],p->ch[1]->mxd[i]);
p->mnd[i]=min(p->mnd[i],p->ch[1]->mnd[i]);
}
}
}
int mindis(nod *p,Poi poi){
int sum=0;
for(int i=0;i<K;i++){
if(poi.d[i]<p->mnd[i]) sum+=p->mnd[i]-poi.d[i];
else if(poi.d[i]>p->mxd[i]) sum+=poi.d[i]-p->mxd[i];
}
return sum;
}
void build(nod **p,int L,int R,int flag){
if(L>R) return ;
*p=&pool[tot++];
if(L==R){
(*p)->poi=a[L];
for(int i=0;i<K;i++) (*p)->mxd[i]=(*p)->mnd[i]=a[L].d[i];
return ;
}
int M=(L+R)>>1;
flg=flag;
nth_element(a+L,a+M,a+R+1);
(*p)->poi=a[M];
build(&(*p)->ch[0],L,M-1,(flag+1)%K);
build(&(*p)->ch[1],M+1,R,(flag+1)%K);
update(*p);
}
void insert(nod **p,Poi poi,int flag){
if(*p==NULL){
*p=&pool[tot++];
(*p)->poi=poi;
for(int i=0;i<K;i++) (*p)->mxd[i]=(*p)->mnd[i]=poi.d[i];
return ;
}
if(poi.d[flag]<=(*p)->poi.d[flag]) insert(&(*p)->ch[0],poi,(flag+1)%K);
else insert(&(*p)->ch[1],poi,(flag+1)%K);
update(*p);
}
void query(nod *p,Poi poi){
int dis0=abs(p->poi.d[0]-poi.d[0])+abs(p->poi.d[1]-poi.d[1]),dis[2];
if(dis0<mn) mn=dis0;
if(p->ch[0]!=NULL) dis[0]=mindis(p->ch[0],poi);
if(p->ch[1]!=NULL) dis[1]=mindis(p->ch[1],poi);
bool t=dis[0]>dis[1];
if(p->ch[t]!=NULL&&dis[t]<mn) query(p->ch[t],poi);
t^=1;
if(p->ch[t]!=NULL&&dis[t]<mn) query(p->ch[t],poi);
}
};

int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=0;j<K;j++)
scanf("%d",&a[i].d[j]);
Kdtree T;
for(int i=1;i<=m;i++){
int t,x,y;
scanf("%d%d%d",&t,&x,&y);
if(t==1) T.insert(&T.root,Poi(x,y),0);
else{
mn=INF;
T.query(T.root,Poi(x,y));
printf("%d\n",mn);
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: