[BZOJ4520][Cqoi2016]K远点对(KD-tree)

来源:互联网 发布:网页优化ppt模板 编辑:程序博客网 时间:2024/09/21 06:32

题目:

我是超链接

题解:

喵喵喵拿到题就开始冥思苦想啦
首先面临的问题就是每一对点都会被计算两次(x,y)&(y,x)
喵喵喵一开始还想用hash,后来发现直接把k*2不就行了orz
这里用了一个小根堆,这样才可以一下把最小的拿出来比较比较看看t不t出去
而且在这个地方

if (dl<dr)    {        if (dr>q.top()) ask(t[now].r);        if (dl>q.top()) ask(t[now].l);     }

不能换成 if(dr>q.top() || q.size() < k))这样你的输出就充满了00000
不管是求最小是的INF还是求最大时的0,都是代表ta没有这个子树!!我们不能为了达到个数不择路径走到空树上去

代码:

#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define LL long longusing namespace std;struct hh{int d[2],l,r,mn[2],mx[2];}t[100005];int cmpd,k,x,y;priority_queue<LL,vector<LL>,greater<LL> >q;int cmp(const hh &a,const hh &b){    return (a.d[cmpd]<b.d[cmpd] || (a.d[cmpd]==b.d[cmpd] && a.d[!cmpd]<b.d[!cmpd]));}void updata(int now){    int lc=t[now].l,rc=t[now].r;    if (lc)    {        t[now].mn[0]=min(t[now].mn[0],t[lc].mn[0]);        t[now].mn[1]=min(t[now].mn[1],t[lc].mn[1]);        t[now].mx[0]=max(t[now].mx[0],t[lc].mx[0]);        t[now].mx[1]=max(t[now].mx[1],t[lc].mx[1]);    }    if (rc)    {        t[now].mn[0]=min(t[now].mn[0],t[rc].mn[0]);        t[now].mn[1]=min(t[now].mn[1],t[rc].mn[1]);        t[now].mx[0]=max(t[now].mx[0],t[rc].mx[0]);        t[now].mx[1]=max(t[now].mx[1],t[rc].mx[1]);    }}int build(int l,int r,int D){    cmpd=D;    int mid=(l+r)>>1;    nth_element(t+l+1,t+mid+1,t+r+1,cmp);    t[mid].mn[0]=t[mid].mx[0]=t[mid].d[0];    t[mid].mn[1]=t[mid].mx[1]=t[mid].d[1];    if (l!=mid) t[mid].l=build(l,mid-1,!D);    if (r!=mid) t[mid].r=build(mid+1,r,!D);    updata(mid); return mid;}LL pf(LL x){return (LL)x*(LL)x;}LL dis(int now){    LL d=0;    d+=max(pf(t[now].mn[0]-x),pf(t[now].mx[0]-x));    d+=max(pf(t[now].mn[1]-y),pf(t[now].mx[1]-y));    return d;}void ask(int now){    LL d0=0,dl,dr;    d0=pf(t[now].d[0]-x)+pf(t[now].d[1]-y);    if (q.size()<k) q.push(d0);    else if (q.top()<d0) q.pop(),q.push(d0);    if (t[now].l) dl=dis(t[now].l);else dl=0;    if (t[now].r) dr=dis(t[now].r);else dr=0;    if (dl<dr)    {        if (dr>q.top()) ask(t[now].r);        if (dl>q.top()) ask(t[now].l);     }    else     {        if (dl>q.top()) ask(t[now].l);        if (dr>q.top()) ask(t[now].r);    }}int main(){    int n,root,i;    scanf("%d%d",&n,&k);k*=2;    for (i=1;i<=n;i++) scanf("%d%d",&t[i].d[0],&t[i].d[1]);    root=build(1,n,0);    for (int i=1;i<=n;i++)     {        x=t[i].d[0]; y=t[i].d[1];        ask(root);    }    printf("%lld",q.top());}
阅读全文
1 0