bzoj4533 [BeiJing2014 WinterCamp] 数据

来源:互联网 发布:域名rp怎么提高 编辑:程序博客网 时间:2024/06/01 07:31

【题意】

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 2147483647using namespace std; struct aa{int d[2];}a[N];struct tt{int l, r, d[2], mx[2], mn[2];}t[N];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[n].d[1]=y;            kd_ins(1, a[n].d[0], a[n].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;}


0 0
原创粉丝点击