bzoj2648&2716 SJY摆棋子 (Kd-Tree)

来源:互联网 发布:淘宝网跑步机 编辑:程序博客网 时间:2024/05/14 11:03

bzoj3503 [Cqoi2014]和谐矩阵

原题地址
http://www.lydsy.com/JudgeOnline/problem.php?id=2648
http://www.lydsy.com/JudgeOnline/problem.php?id=2716

题意:
在一个棋盘上,有N个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) 。现在给出N<=500000个初始棋子。和M<=500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。

数据范围
kdtree可以过。

题解:
裸的Kd-Tree。
像平衡树一样的插入。
我没有重构。

代码:

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<cmath>using namespace std;const int inf=0x3f3f3f3f;const int N=1000006;int n,m,cur,tail=0,ans,root;struct node{    int ls,rs,d[2],mx[2],mn[2];}tr[N],t;bool cmp(const node &A,const node &B){return A.d[cur]<B.d[cur];}void update(int nd){    int ls=tr[nd].ls; int rs=tr[nd].rs;    if(ls)     {        tr[nd].mx[0]=max(tr[nd].mx[0],tr[ls].mx[0]);        tr[nd].mn[0]=min(tr[nd].mn[0],tr[ls].mn[0]);        tr[nd].mx[1]=max(tr[nd].mx[1],tr[ls].mx[1]);        tr[nd].mn[1]=min(tr[nd].mn[1],tr[ls].mn[1]);    }    if(rs)     {        tr[nd].mx[0]=max(tr[nd].mx[0],tr[rs].mx[0]);        tr[nd].mn[0]=min(tr[nd].mn[0],tr[rs].mn[0]);        tr[nd].mx[1]=max(tr[nd].mx[1],tr[rs].mx[1]);        tr[nd].mn[1]=min(tr[nd].mn[1],tr[rs].mn[1]);        }}void build(int &nd,int lf,int rg,int now){    int mid=(lf+rg)>>1; nd=mid; cur=now;    nth_element(tr+lf,tr+mid,tr+rg+1,cmp);    tr[nd].mx[0]=tr[nd].mn[0]=tr[nd].d[0];    tr[nd].mx[1]=tr[nd].mn[1]=tr[nd].d[1];    if(lf<mid) build(tr[nd].ls,lf,mid-1,now^1);    if(rg>mid) build(tr[nd].rs,mid+1,rg,now^1);    update(nd);}void insert(int nd,int now){    cur=now;    if(cmp(t,tr[nd]))     {        if(tr[nd].ls) insert(tr[nd].ls,now^1);        else {tr[nd].ls=++tail; tr[tail]=t;}    }    else     {        if(tr[nd].rs) insert(tr[nd].rs,now^1);        else { tr[nd].rs=++tail; tr[tail]=t;}    }    update(nd);}int abs(int x){return x<0?-x:x;}int dis(node A,node B) {return abs(A.d[0]-B.d[0])+abs(A.d[1]-B.d[1]);}int cal(node &x){    int ret=0;    for(int i=0;i<2;i++)    {        if(t.d[i]>x.mx[i]) ret+=t.d[i]-x.mx[i];        if(t.d[i]<x.mn[i]) ret+=x.mn[i]-t.d[i];    }    return ret;}void query(int nd){    ans=min(ans,dis(tr[nd],t)); int dl,dr;    if(tr[nd].ls) dl=cal(tr[tr[nd].ls]); else dl=inf;    if(tr[nd].rs) dr=cal(tr[tr[nd].rs]); else dr=inf;    if(dl<dr)    {        if(dl<ans) query(tr[nd].ls);        if(dr<ans) query(tr[nd].rs);    }    else    {        if(dr<ans) query(tr[nd].rs);        if(dl<ans) query(tr[nd].ls);    }}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++) scanf("%d%d",&tr[i].d[0],&tr[i].d[1]);    build(root,1,n,0); tail=n;    while(m--)    {        int opt; scanf("%d%d%d",&opt,&t.d[0],&t.d[1]);        if(opt==1)        {            for(int i=0;i<2;i++) t.mx[i]=t.mn[i]=t.d[i];            insert(root,0);        }        else {ans=inf; query(root); printf("%d\n",ans);}    }    return 0;}
原创粉丝点击