【BZOJ 2716/2648】 [Violet 3]天使玩偶

来源:互联网 发布:server2012 mysql集群 编辑:程序博客网 时间:2024/05/01 14:12

2716: [Violet 3]天使玩偶

kd-tree模板题。

①首先依次按照每一维(即先按照x,再按照y,再按照x…多维同理)将点存在一棵二叉树中:
先求出以当前维数为关键字的中间点是谁(用到nth_element这个函数,可以直接把排名为k的放在第k位上,不保证其他有序:nth_element(a+1,a+1+k,a+1+n,cmp))

为了一会儿查询中求估价函数方便,需要记录一下当前节点的子树中各维的极值(max,min)

②插入操作与splay的插入操作同理。

③询问操作的本质是搜索+用估价函数剪枝(估价函数的结果一定比实际最优解小),先搜索更优的,用更优的那个子树更新答案;判断次优的子树的估价函数是否小于当前答案,可以发现这个概率是比较小的,进入次优子树搜索的概率就小一些。

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#define inf 0x3f3f3f3f#define M 2000005using namespace std;int k,x[2],root,ans,now,n,m;struct node{    int ma[2],mi[2],d[2],l,r;}t[M];void read(int &tmp){    tmp=0;    char ch=getchar();    int fu=1;    for (;ch<'0'||ch>'9';ch=getchar())        if (ch=='-') fu=-1;    for (;ch>='0'&&ch<='9';ch=getchar())        tmp=tmp*10+ch-'0';    tmp*=fu;}bool cmp(node a,node b){    if (a.d[now]==b.d[now])        return a.d[now^1]<b.d[now^1];    return a.d[now]<b.d[now];}void Update(int x){    int l=t[x].l,r=t[x].r;    for (int i=0;i<2;i++)    {        t[x].ma[i]=max(t[x].ma[i],max(t[l].ma[i],t[r].ma[i]));        t[x].mi[i]=min(t[x].mi[i],min(t[l].mi[i],t[r].mi[i]));    }}int Build(int l,int r,int k){    int m=(l+r)>>1;    now=k;    nth_element(t+l+1,t+m+1,t+r+1,cmp);    for (int i=0;i<2;i++)        t[m].ma[i]=t[m].mi[i]=t[m].d[i];    if (l!=m)        t[m].l=Build(l,m-1,k^1);    if (r!=m)        t[m].r=Build(m+1,r,k^1);    Update(m);    return m;}void Insert(int now){    int k=0,p=root;    while (1)    {        for (int i=0;i<2;i++)        {            t[p].ma[i]=max(t[p].ma[i],t[now].ma[i]);            t[p].mi[i]=min(t[p].mi[i],t[now].mi[i]);        }        if (t[now].d[k]>=t[p].d[k])        {            if (!t[p].r)            {                t[p].r=now;                return;            }            else p=t[p].r;        }        else        {            if (!t[p].l)            {                t[p].l=now;                return;            }            else p=t[p].l;        }        k=k^1;    }}int Dis(int p){    return abs(t[p].d[0]-x[0])+abs(t[p].d[1]-x[1]);}int Get(int p){    int ans=0;    for (int i=0;i<2;i++)        ans+=max(0,t[p].mi[i]-x[i])+max(0,x[i]-t[p].ma[i]);    return ans;}void Query(int p){    if (!p) return;    int d0=Dis(p),dl=Get(t[p].l),dr=Get(t[p].r);    if (d0<ans) ans=d0;    if (dl<dr)    {        if (dl<ans) Query(t[p].l);        if (dr<ans) Query(t[p].r);    }    else    {        if (dr<ans) Query(t[p].r);        if (dl<ans) Query(t[p].l);    }}int main(){    scanf("%d%d",&n,&m);    t[0].ma[0]=t[0].ma[1]=-inf,t[0].mi[0]=t[0].mi[1]=inf;    for (int i=1;i<=n;i++)        read(t[i].d[0]),read(t[i].d[1]);    root=Build(1,n,0);    for (int i=1;i<=m;i++)    {        read(k),read(x[0]),read(x[1]);        if (k==1)        {            n++;            for (int j=0;j<2;j++)                t[n].ma[j]=t[n].mi[j]=t[n].d[j]=x[j];            Insert(n);        }        else        {            ans=inf;            Query(root);            printf("%d",ans);            putchar('\n');        }    }    return 0;}

这里写图片描述

3 1
原创粉丝点击