• P4169 [Violet]天使玩偶/SJY摆棋子


    题目背景

    感谢@浮尘ii 提供的一组hack数据

    题目描述

    Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下。而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里,所以她决定仅凭一点模糊的记忆来寻找它。

    我们把 Ayu 生活的小镇看作一个二维平面坐标系,而 Ayu 会不定时地记起可能在某个点 (xmy) 埋下了天使玩偶;或者 Ayu 会询问你,假如她在 (x,y) ,那么她离近的天使玩偶可能埋下的地方有多远。

    因为 Ayu 只会沿着平行坐标轴的方向来行动,所以在这个问题里我们定义两个点之间的距离为dist(A,B)=|Ax-Bx|+|Ay-By|。其中 Ax 表示点 A的横坐标,其余类似。

    输入输出格式

    输入格式:

    第一行包含两个整数n和m ,在刚开始时,Ayu 已经知道有n个点可能埋着天使玩偶, 接下来 Ayu 要进行m 次操作

    接下来n行,每行两个非负整数 (xi,yi),表示初始n个点的坐标。

    再接下来m 行,每行三个非负整数 t,xi,yi。

    如果t=1 ,则表示 Ayu 又回忆起了一个可能埋着玩偶的点 (xi,yi) 。

    如果t=2 ,则表示 Ayu 询问如果她在点 (xi,yi) ,那么在已经回忆出来的点里,离她近的那个点有多远

    输出格式:

    对于每个t=2 的询问,在单独的一行内输出该询问的结果。

    输入输出样例

    输入样例#1: 
    2 3 
    1 1 
    2 3 
    2 1 2 
    1 3 3 
    2 4 2
    输出样例#1: 
    1 
    2

    说明

    n,m<=300 000

    xi,yi<=1 000 000

    Solution:
      本题巨说是点分治裸题。。。然而我用$kd-tree$水了波$90$。(应该是可以$A$的,但是暂时不会玄学转树,留坑待填~)

      有必要先解释一下变量含义:$(d[0],d[1])$为当前根节点的坐标,$(mn[0],mn[1])$表示当前节点代表的二维平面中最左下角的坐标,$(mx[0],mx[1])$表示最右上角的坐标,$l,r$分别表示当前节点的左、右儿子。

      思路比较简单,构建二维搜索树,将每个点拍到面上去,从根节点往下每层交替按$x$和$y$为关键字建树。

      建树过程,要尽可能使得树保持平衡,所以每次以区间中间为当前根节点建树,二维平面分为左部和右部两部分,分别表示当前节点的左儿子和右儿子。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define Min(a,b) ((a)>(b)?(b):(a))
    #define Max(a,b) ((a)>(b)?(a):(b))
    using namespace std;
    const int N=800005,inf=23333333;
    int n,m,x,y,opt,ans,cmpd,root;
    struct node{
        int d[2],l,r,mn[2],mx[2];
        bool operator <(const node a){
            return ((d[cmpd]<a.d[cmpd])||(d[cmpd]==a.d[cmpd]&&d[!cmpd]<a.d[!cmpd]));
        }
    }t[N];
    
    il int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar();
        return f?-a:a;
    }
    
    il void update(int rt){
        int ls=t[rt].l,rs=t[rt].r;
        if(ls){
            t[rt].mn[0]=Min(t[rt].mn[0],t[ls].mn[0]);
            t[rt].mn[1]=Min(t[rt].mn[1],t[ls].mn[1]);
            t[rt].mx[0]=Max(t[rt].mx[0],t[ls].mx[0]);
            t[rt].mx[1]=Max(t[rt].mx[1],t[ls].mx[1]);
        }
        if(rs){
            t[rt].mn[0]=Min(t[rt].mn[0],t[rs].mn[0]);
            t[rt].mn[1]=Min(t[rt].mn[1],t[rs].mn[1]);
            t[rt].mx[0]=Max(t[rt].mx[0],t[rs].mx[0]);
            t[rt].mx[1]=Max(t[rt].mx[1],t[rs].mx[1]);
        }
    }
    
    il int build(int l,int r,int tw){
        cmpd=tw;
        int mid=l+r>>1;
        nth_element(t+l+1,t+mid+1,t+r+1);
        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,!tw);
        if(r!=mid)t[mid].r=build(mid+1,r,!tw);
        update(mid);
        return mid;
    }
    
    il void insert(int rt){
        int op=0,p=root;
        while(1){
            if(t[rt].mn[0]<t[p].mn[0])t[p].mn[0]=t[rt].mn[0];
            if(t[rt].mn[1]<t[p].mn[1])t[p].mn[1]=t[rt].mn[1];
            if(t[rt].mx[0]>t[p].mx[0])t[p].mx[0]=t[rt].mx[0];
            if(t[rt].mx[1]>t[p].mx[1])t[p].mx[1]=t[rt].mx[1];
            if(t[rt].d[op]>=t[p].d[op]){
                if(!t[p].r){t[p].r=rt;return;}
                else p=t[p].r;
            }
            else {
                if(!t[p].l){t[p].l=rt;return;}
                else p=t[p].l;
            }
            op=!op;
        }
    }
    
    il int mhd(int rt,int x,int y){
        int s=0;
        if(x<t[rt].mn[0])s+=(t[rt].mn[0]-x);
        if(x>t[rt].mx[0])s+=(x-t[rt].mx[0]);
        if(y<t[rt].mn[1])s+=(t[rt].mn[1]-y);
        if(y>t[rt].mx[1])s+=(y-t[rt].mx[1]);
        return s;
    }
    
    il void query(int rt){
        int d0,dl,dr;
        d0=abs(t[rt].d[0]-x)+abs(t[rt].d[1]-y);
        if(d0<ans)ans=d0;
        if(t[rt].l)dl=mhd(t[rt].l,x,y);
        else dl=inf;
        if(t[rt].r)dr=mhd(t[rt].r,x,y);
        else dr=inf;
        if(dl<dr){
            if(dl<ans)query(t[rt].l);
            if(dr<ans)query(t[rt].r);
        }
        else {
            if(dr<ans)query(t[rt].r);
            if(dl<ans)query(t[rt].l);
        }
    }
    
    int main(){
        n=gi(),m=gi();
        For(i,1,n) t[i].d[0]=gi(),t[i].d[1]=gi();
        root=build(1,n,0);
        while(m--){
            opt=gi(),x=gi(),y=gi();
            if(opt==1){
                n++;
                t[n].mn[0]=t[n].mx[0]=t[n].d[0]=x;
                t[n].mn[1]=t[n].mx[1]=t[n].d[1]=y;
                insert(n);
            }
            else {
                ans=inf;
                query(root);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    【VUE】自定义组件
    【docker】Dockerfile
    【docker】常用命令
    【Java Web开发学习】跨域请求
    xshell6和xftp6运行提示缺少mfc110u.dll文件的解决办法
    【NPM】使用问题记录
    【Zuul】使用学习
    第八章 泛型程序设计
    第九章 集合
    分布式系列二: 分布式系统的通信
  • 原文地址:https://www.cnblogs.com/five20/p/9164230.html
Copyright © 2020-2023  润新知