BZOJ2648:SJY摆棋子(KDtree)

传送门
这道题和BZOJ2716一样:http://blog.csdn.net/qq_35649707/article/details/77800032

不过CDQ过不了。。。
于是写了KD树。。其实就是一个玄学DFS减枝。
表示写了一个替罪羊树套在里面还变慢了。。

#include<bits/stdc++.h>
using namespace std;

struct IO{
    streambuf *ib,*ob;
    inline void init(){
        ios::sync_with_stdio(false);
        cin.tie(NULL),cout.tie(NULL);
        ib=cin.rdbuf();ob=cout.rdbuf();
    }
    inline int read(){
        char ch=ib->sbumpc();int i=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
        while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}
        return i*f;
    }
    inline void W(int x){
        static int buf[50];
        if(!x){ob->sputc('0');ob->sputc('\n');return;}
        if(x<0){ob->sputc('-');x=-x;}
        while(x){buf[++buf[0]]=x%10;x/=10;}
        while(buf[0])
        {ob->sputc(buf[buf[0]--]+'0');}
        ob->sputc('\n');
    }
}io;

const int INF=0x3f3f3f3f;
const int Maxn=1e6+50;
int n,m;

struct point{
    int x[2];
    point(int x=0,int y=0){
        this->x[0]=x;this->x[1]=y;
    }
    inline int dist(point p){
        return abs(p.x[0]-this->x[0])+abs(p.x[1]-this->x[1]);
    }
}pp[Maxn];
inline bool cmp0(const point &a,const point &b){
    return a.x[0]<b.x[0];
}
inline bool cmp1(const point &a,const point &b){
    return a.x[1]<b.x[1];
}
struct node{
    node *c[2];
    point p;
    int mx[2],mn[2];
    inline void upt(node *c);
}Pool[Maxn],*pool=Pool,*null=pool;
inline node* newnode(point p){
    ++pool;
    pool->c[0]=pool->c[1]=null;
    pool->p=p;
    pool->mx[0]=pool->mn[0]=p.x[0];
    pool->mx[1]=pool->mn[1]=p.x[1];
    return pool;
}
void node::upt(node *c){
    mx[0]=max(mx[0],c->mx[0]);mn[0]=min(mn[0],c->mn[0]);
    mx[1]=max(mx[1],c->mx[1]);mn[1]=min(mn[1],c->mn[1]);
}
struct KDimTree{
    node *rt;
    KDimTree():rt(null){}
    inline void insert(node*& now,int dim,point p){
        if(now==null){now=newnode(p);return;}
        if(p.x[dim]<now->p.x[dim])insert(now->c[0],dim^1,p),now->upt(now->c[0]);
        else insert(now->c[1],dim^1,p),now->upt(now->c[1]);
    }
    inline int mindist(node *now,point p){
        if(now==null)return INF;
        int res=0;
        for(int i=0;i<2;i++){
            if(now->mn[i]>p.x[i])res+=now->mn[i]-p.x[i];
            else if(now->mx[i]<p.x[i])res+=p.x[i]-now->mx[i];
        }
        return res;
    }
    inline void query(node* now,point p,int &ans){
        if(now==null)return;
        ans=min(ans,p.dist(now->p));
        int dl=mindist(now->c[0],p),dr=mindist(now->c[1],p);
        if(dl<dr){
            if(dl<ans)query(now->c[0],p,ans);
            if(dr<ans)query(now->c[1],p,ans);
        }
        else{
            if(dr<ans)query(now->c[1],p,ans);
            if(dl<ans)query(now->c[0],p,ans);
        }
    }
    inline void build(node*& now,point* p,int l,int r,int dim){
        int mid=(l+r)>>1;
        if(dim)nth_element(p+l,p+mid,p+r+1,cmp1);
        else nth_element(p+l,p+mid,p+r+1,cmp0);
        now=newnode(p[mid]);
        if(l==r)return;
        if(l<mid)build(now->c[0],p,l,mid-1,dim^1),now->upt(now->c[0]);
        if(mid<r)build(now->c[1],p,mid+1,r,dim^1),now->upt(now->c[1]);
    }
}kdtree;

int main(){
    io.init();n=io.read(),m=io.read();
    for(int i=1;i<=n;i++){
        pp[i].x[0]=io.read(),pp[i].x[1]=io.read();
    }
    kdtree.build(kdtree.rt,pp,1,n,0);
    for(int i=1;i<=m;i++){
        int op=io.read(),x=io.read(),y=io.read();
        if(op==1){
            kdtree.insert(kdtree.rt,0,point(x,y));
        }
        else{
            int ans=INF;
            kdtree.query(kdtree.rt,point(x,y),ans);
            io.W(ans);
        }
    }
}
  #include<bits/stdc++.h>
using namespace std;

struct IO{
    streambuf *ib,*ob;
    inline void init(){
        ios::sync_with_stdio(false);
        cin.tie(NULL),cout.tie(NULL);
        ib=cin.rdbuf();ob=cout.rdbuf();
    }
    inline int read(){
        char ch=ib->sbumpc();int i=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
        while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}
        return i*f;
    }
    inline void W(int x){
        static int buf[50];
        if(!x){ob->sputc('0');ob->sputc('\n');return;}
        if(x<0){ob->sputc('-');x=-x;}
        while(x){buf[++buf[0]]=x%10;x/=10;}
        while(buf[0])
        {ob->sputc(buf[buf[0]--]+'0');}
        ob->sputc('\n');
    }
}io;

const int INF=0x3f3f3f3f;
const int Maxn=1e6+50;
int n,m;

struct point{
    int x[2];
    point(int x=0,int y=0){
        this->x[0]=x;this->x[1]=y;
    }
    inline int dist(point p){
        return abs(p.x[0]-this->x[0])+abs(p.x[1]-this->x[1]);
    }
}pp[Maxn];
inline bool cmp0(const point &a,const point &b){
    return a.x[0]<b.x[0];
}
inline bool cmp1(const point &a,const point &b){
    return a.x[1]<b.x[1];
}
struct node{
    node *c[2];
    point p;
    int mx[2],mn[2],sze,nowdim;
    inline void upt();
}Pool[Maxn],*pool=Pool,*null=pool,*recyclepool[Maxn];
int pooltail;
inline node* newnode(point p){
    node *tmp=(pooltail==0)?(++pool):(recyclepool[pooltail--]);
    tmp->c[0]=tmp->c[1]=null;
    tmp->p=p;tmp->sze=1;
    tmp->mx[0]=tmp->mn[0]=p.x[0];
    tmp->mx[1]=tmp->mn[1]=p.x[1];
    return tmp;
}
void node::upt(){
    sze=1;
    for(int i=0;i<2;i++){
        if(c[i]==null)continue;
        mx[0]=max(mx[0],c[i]->mx[0]);mn[0]=min(mn[0],c[i]->mn[0]);
        mx[1]=max(mx[1],c[i]->mx[1]);mn[1]=min(mn[1],c[i]->mn[1]);
        sze+=c[i]->sze;
    }
}
const int alpha=78;
struct KDimTree{
    node *rt;
    KDimTree():rt(null){}
    inline void insert(node*& now,int dim,point p,node**& o){
        if(now==null){now=newnode(p);now->nowdim=dim;return;}
        if(p.x[dim]<now->p.x[dim])insert(now->c[0],dim^1,p,o);
        else insert(now->c[1],dim^1,p,o);
        now->upt();
        if(now->c[0]->sze*100>now->sze*alpha||now->c[1]->sze*100>now->sze*alpha)o=&now;
    }
    inline int mindist(node *now,point p){
        if(now==null)return INF;
        int res=0;
        for(int i=0;i<2;i++){
            if(now->mn[i]>p.x[i])res+=now->mn[i]-p.x[i];
            else if(now->mx[i]<p.x[i])res+=p.x[i]-now->mx[i];
        }
        return res;
    }
    inline void query(node* now,point p,int &ans){
        if(now==null)return;
        ans=min(ans,p.dist(now->p));
        int dl=mindist(now->c[0],p),dr=mindist(now->c[1],p);
        if(dl<dr){
            if(dl<ans)query(now->c[0],p,ans);
            if(dr<ans)query(now->c[1],p,ans);
        }
        else{
            if(dr<ans)query(now->c[1],p,ans);
            if(dl<ans)query(now->c[0],p,ans);
        }
    }
    inline void build(node*& now,point* p,int l,int r,int dim){
        int mid=(l+r)>>1;
        if(dim)nth_element(p+l,p+mid,p+r+1,cmp1);
        else nth_element(p+l,p+mid,p+r+1,cmp0);
        now=newnode(p[mid]);
        now->nowdim=dim;
        if(l==r)return;
        if(l<mid)build(now->c[0],p,l,mid-1,dim^1);
        if(mid<r)build(now->c[1],p,mid+1,r,dim^1);
        now->upt();
    }
    inline void travel(node *now,int &tail){
        if(now==null)return;
        travel(now->c[0],tail);
        pp[++tail]=now->p;recyclepool[++pooltail]=now;
        travel(now->c[1],tail);
        now=null;
    }
    inline void rebuild(node *&now){
        static int tail;
        tail=0;
        int dim=now->nowdim;
        travel(now,tail);
        build(now,pp,1,tail,dim);
    }
}kdtree;

int main(){
    io.init();n=io.read(),m=io.read();
    for(int i=1;i<=n;i++){
        pp[i].x[0]=io.read(),pp[i].x[1]=io.read();
    }
    kdtree.build(kdtree.rt,pp,1,n,0);
    for(int i=1;i<=m;i++){
        int op=io.read(),x=io.read(),y=io.read();
        if(op==1){
            node ** o=&null;
            kdtree.insert(kdtree.rt,0,point(x,y),o);
            if(*o!=null)kdtree.rebuild(*o);
        }
        else{
            int ans=INF;
            kdtree.query(kdtree.rt,point(x,y),ans);
            io.W(ans);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值