您的位置:首页 > 其它

bzoj4533 [BeiJing2014 WinterCamp] 数据

2016-12-10 22:42 218 查看
【题意】

n个点,m个操作,共3种:

1.加点

2.查询点集到定点曼哈顿距离最小值

3.查询点集到定点曼哈顿距离最大值

【数据范围】

n<=100000,m<=100000

【思路】

kd-tree模板题。

求曼哈顿距离最小值:

估价函数为该点与边框矩形的最小距离,优先查询估价小的子树,若子树估价>=ans则忽略此子树。

求曼哈顿距离最大值:

估价函数为该点与边框4个顶点的最大距离(即该点与边框矩形的最大距离),优先查询估价大的子树,若子树估价<=ans则忽略此子树。

【时间复杂度】

O((n+m)sqrt(n+m))

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 200010
#define inf 2147483647
using namespace std;

struct aa{int d[2];}a
;
struct tt{int l, r, d[2], mx[2], mn[2];}t
;
int n, B, m, l, D, x, y, ans, temp;

inline int read(){
int x=0, f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
}

bool operator<(aa a, aa b){return a.d[D]<b.d[D];}

void update(int i){
for(int j=0; j<=1; j++){
t[i].mx[j]=t[i].mn[j]=t[i].d[j];
if(t[i].l){
t[i].mx[j]=max(t[i].mx[j], t[t[i].l].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].l].mn[j]);
}
if(t[i].r){
t[i].mx[j]=max(t[i].mx[j], t[t[i].r].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].r].mn[j]);
}
}
}

void kd_maketree(int L, int R, int now){
t[l].l=t[l].r=0; D=now;
int mid=(L+R)>>1;
nth_element(a+L, a+mid, a+R+1);
t[l].d[0]=a[mid].d[0]; t[l].d[1]=a[mid].d[1];
int l1=l;
if(L<mid){l++; t[l1].l=l; kd_maketree(L, mid-1, now^1);}
if(mid<R){l++; t[l1].r=l; kd_maketree(mid+1, R, now^1);}
update(l1);
}

void kd_ins(int i, int x, int y, int now, int fa, int p){
if(!i){
l++; t[l].l=t[l].r=0;
t[l].d[0]=x; t[l].d[1]=y; update(l);
if(!p)t[fa].l=l; else t[fa].r=l;
return;
}
if(t[i].d[0]==x&&t[i].d[1]==y)return;
if(!now){
if(x<=t[i].d[0])kd_ins(t[i].l, x, y, now^1, i, 0);
else kd_ins(t[i].r, x, y, now^1, i, 1);
}else{
if(y<=t[i].d[1])kd_ins(t[i].l, x, y, now^1, i, 0);
else kd_ins(t[i].r, x, y, now^1, i, 1);
}
update(i);
}

int getmn(int i, int x, int y){
return max(t[i].mn[0]-x, 0)+max(x-t[i].mx[0], 0)+max(t[i].mn[1]-y, 0)+max(y-t[i].mx[1], 0);
}
int getmx(int i, int x, int y){
return max(abs(x-t[i].mn[0]), abs(x-t[i].mx[0]))+max(abs(y-t[i].mn[1]), abs(y-t[i].mx[1]));
}

void cmn(int i, int x, int y){
if(!i)return;
ans=min(ans, abs(t[i].d[0]-x)+abs(t[i].d[1]-y));
int h1=t[i].l?getmn(t[i].l, x, y):inf;
int h2=t[i].r?getmn(t[i].r, x, y):inf;
if(h1<=h2){
if(ans>h1)cmn(t[i].l, x, y);
if(ans>h2)cmn(t[i].r, x, y);
}else{
if(ans>h2)cmn(t[i].r, x, y);
if(ans>h1)cmn(t[i].l, x, y);
}
}
void cmx(int i, int x, int y){
if(!i)return;
ans=max(ans, abs(t[i].d[0]-x)+abs(t[i].d[1]-y));
int h1=t[i].l?getmx(t[i].l, x, y):0;
int h2=t[i].r?getmx(t[i].r, x, y):0;
if(h1>=h2){
if(ans<h1)cmx(t[i].l, x, y);
if(ans<h2)cmx(t[i].r, x, y);
}else{
if(ans<h2)cmx(t[i].r, x, y);
if(ans<h1)cmx(t[i].l, x, y);
}
}

int main(){
n=read();
for(int i=1; i<=n; i++){a[i].d[0]=read(); a[i].d[1]=read();}
l=1; kd_maketree(1, n, 0);
B=n+10000;
m=read();
for(int i=1; i<=m; i++){
temp=read(); x=read(); y=read();
if(!temp){
a[++n].d[0]=x; a
.d[1]=y;
kd_ins(1, a
.d[0], a
.d[1], 0, 0, 0);
if(n==B){
l=1; kd_maketree(1, n, 0);
B+=10000;
}
}
if(temp==1){ans=inf; cmn(1, x, y); printf("%d\n", ans);}
if(temp==2){ans=0; cmx(1, x, y); printf("%d\n", ans);}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: