• [WC2013]平面图——平面图点定位


    [WC2013]平面图 

    码农题

    平面图点定位:

    1.平面图转对偶图:[HNOI2016]矿区

    2.扫描线点定位

    把所有的顶点和询问点排序,扫描线

    每个边在fr的位置加入,to的位置删除,竖直直线不要

    用set维护当前的线段,kx+b形式

    全局变量X放入重载小于号的比较函数,便于直接比较

    到了询问点,直接查询上方第一个线段,得到这个线段所属对偶图新点的编号,即可得到这个询问点的位置

    (需要在线就可持久化平衡树吧。。)

    trick:

    A.可以把询问点当做:0*x+p[i].y,直接查询即可

    B.避免插入删除时候纵坐标一样的麻烦,X+=0.1后插入,X-=0.1后删除

    C.询问上方第一个线段,(我的对偶图内部是顺时针),所以保留to的横坐标比fr的大的边即可,省去了线段重合的麻烦

     

    然后求MST之后倍增找到链上最大值即可

    实现

    扫描线时候:

    直接开vector把涉及的插入线段,删除线段,询问点直接塞进去,直接查询即可

    可能有重边!

    这个时候必须保留最小值,先把所有边sort之后再加入。

    但是注意:b[++m]=bian(...,...,...m)bian构造函数传进去的m还是之前的m!并没有++m

    所以把++m放外面先做

    另外,总涉及点数是3*n的。

     

    大致解释

    code:并不能过UOJhack数据

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    #define pb push_back
    #define solid const auto &
    #define enter cout<<endl
    #define pii pair<int,int>
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);}
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    
    namespace Miracle{
    const int N=1e5+5;
    const int inf=0x3f3f3f3f;
    int n,m,q;
    struct lj{
        int x,y,z;
        bool friend operator <(lj a,lj b){
            return a.z<b.z;
        }
    }name[N];
    map<pii,int>exi;
    //pre---------------------------------------------------------------------------//
    struct po{
        double x,y;
        po(){}
        po friend operator -(po a,po b){return po(a.x-b.x,a.y-b.y);}
        po(double xx,double yy){
            x=xx;y=yy;
        }
        bool friend operator <(po a,po b){
            return a.x<b.x;
        }
        double friend operator *(po a,po b){
            return a.x*b.y-a.y*b.x;
        }
    }p[3*N];
    int num;
    double degree(const po &A){
        return atan2(A.y,A.x);
    }
    struct line{
        int fr,to;
        int cos;
        int id;
        double deg;
        line(){}
        line(int a,int b,int c,int d){fr=a;to=b;cos=c;id=d;deg=degree(p[to]-p[fr]);}
        bool friend operator <(line A,line B){
            return A.deg<B.deg;
        }
    }b[2*N];
    vector<line>to[N];
    int nxt[2*N];
    int nc;//newcur
    int be[2*N];
    int findnxt(const line &A,const int &id){
        int lp=upper_bound(to[id].begin(),to[id].end(),A)-to[id].begin();
        if(lp==to[id].size()) lp=0;
        return to[id][lp].id;
    }
    struct edge{
        int x,y,val;
        bool friend operator <(edge a,edge b){
            return a.val<b.val;
        }
    }mao[N];
    int tot;//count
    void trans(){
        for(reg i=1;i<=n;++i) sort(to[i].begin(),to[i].end());
        for(reg i=0;i<=m;++i){
            nxt[i]=findnxt(b[i^1],b[i].to);
        }
        for(reg i=0;i<=m;++i){
            if(be[i]) continue;
            be[i]=be[nxt[i]]=++nc;
            double S=0;
            for(reg j=nxt[i];j!=i;j=nxt[j]){
                be[j]=nc;
                S+=(p[b[j].to]-p[b[i].fr])*(p[b[j].fr]-p[b[i].fr]);
            }   
            if(S<0){
                --nc;
                be[i]=be[nxt[i]]=inf;
                for(reg j=nxt[i];j!=i;j=nxt[j]){
                    be[j]=inf;
                }   
            }
        }
        for(reg i=0;i<=m;i+=2){
            if(be[i]!=inf&&be[i^1]!=inf){
                ++tot;
                mao[tot].x=be[i];
                mao[tot].y=be[i^1];
                mao[tot].val=b[i].cos;
            }
        }
    }
    //trans-------------------------------------------------------------------------//
    int gf[N];
    int fin(int x){
        return gf[x]==x?x:gf[x]=fin(gf[x]);
    }
    struct node{
        int nxt,to;
        int val;
    }e[2*N];
    int hd[N],cnt;
    void add(int x,int y,int z){
        e[++cnt].nxt=hd[x];
        e[cnt].to=y;
        e[cnt].val=z;
        hd[x]=cnt;
    }
    void kruskal(){
        for(reg i=1;i<=nc;++i) gf[i]=i;
        sort(mao+1,mao+tot+1);
        for(reg i=1;i<=tot;++i){
            int x=mao[i].x,y=mao[i].y;
            int k1=fin(x),k2=fin(y);
            if(k1!=k2){
                gf[k1]=k2;
                add(x,y,mao[i].val);
                add(y,x,mao[i].val);
            }
        }
    }
    //kruskal-------------------------------------------------------------------------//
    int dep[N],fa[N][18],mx[N][18];
    void dfs(int x,int d){
        dep[x]=d;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(y==fa[x][0]) continue;
            fa[y][0]=x;
            mx[y][0]=e[i].val;
            dfs(y,d+1);
        }
    }
    int query(int x,int y){
        if(dep[x]<dep[y]) swap(x,y);
        int ret=0;
        for(reg j=17;j>=0;--j){
            if(dep[fa[x][j]]>=dep[y]){
                ret=max(ret,mx[x][j]);x=fa[x][j];
            }
        }
        if(x==y) return ret;
        for(reg j=17;j>=0;--j){
            if(fa[x][j]!=fa[y][j]){
                ret=max(ret,max(mx[x][j],mx[y][j]));
                x=fa[x][j],y=fa[y][j];
            }
        }
        ret=max(ret,max(mx[x][0],mx[y][0]));
        return ret;
    }
    //dfs&&lca------------------------------------------------------------------------//
    double X;
    struct bian{
        double k,b;
        int id;
        bian(){}
        bian(double kk,double bb,double dd){
            k=kk;b=bb;id=dd;
        }
        double f(){return k*X+b;}
        bool friend operator <(bian A,bian B){
            return A.f()<B.f();
        }
        void op() const {
            cout<<" k "<<k<<" b "<<b<<" id "<<id<<endl;
        }
    };
    multiset<bian>s;
    int rk[3*N];
    bool cmp(int x,int y){
        return p[x]<p[y];
    }
    vector<int>qs[3*N];
    vector<bian>del[3*N];
    vector<bian>ins[3*N];
    int qa[N],qb[N];
    int in[3*N];
    int main(){
        rd(n);int lp;rd(lp);
        int x,y;
        for(reg i=1;i<=n;++i){
            rd(x);rd(y);p[++num].x=x;p[num].y=y;
        }
        for(reg i=1;i<=lp;++i){
            rd(name[i].x);rd(name[i].y);rd(name[i].z);if(name[i].x>name[i].y) swap(name[i].x,name[i].y);
        }sort(name+1,name+lp+1);
    
        m=-1;//warning!! m=-1
        for(reg i=1;i<=lp;++i){
            pii tmp=mk(name[i].x,name[i].y);
            if(exi.count(tmp)) continue;
            exi[tmp]=1;++m;
            b[m]=line(name[i].x,name[i].y,name[i].z,m);
            to[name[i].x].push_back(b[m]);
            ++m;
            b[m]=line(name[i].y,name[i].x,name[i].z,m);
            to[name[i].y].push_back(b[m]);
        }
        trans();
        kruskal();
        dfs(1,1);
        for(reg j=1;j<=17;++j){
            for(reg i=1;i<=nc;++i){
                fa[i][j]=fa[fa[i][j-1]][j-1];
                mx[i][j]=max(mx[i][j-1],mx[fa[i][j-1]][j-1]);
            }
        }
        rd(q);
        for(reg i=1;i<=q;++i){
            po tmp;scanf("%lf",&tmp.x);scanf("%lf",&tmp.y);
            ++num;p[num]=tmp;
            qa[i]=num;
            scanf("%lf",&tmp.x);scanf("%lf",&tmp.y);
            ++num;p[num]=tmp;
            qb[i]=num;
            qs[qa[i]].push_back(qa[i]);
            qs[qb[i]].push_back(qb[i]);
        }
        for(reg i=1;i<=num;++i) rk[i]=i;
        sort(rk+1,rk+num+1,cmp);
        for(reg i=0;i<=m;++i){
            if(p[b[i].fr].x<p[b[i].to].x){
                bian tmp;
                tmp.k=(p[b[i].to].y-p[b[i].fr].y)/(p[b[i].to].x-p[b[i].fr].x);
                tmp.b=p[b[i].fr].y-tmp.k*p[b[i].fr].x;
                tmp.id=i;
                ins[b[i].fr].push_back(tmp);
                del[b[i].to].push_back(tmp);
            }
        }
        for(reg i=1;i<=num;++i){
            int now=rk[i];
            if(del[now].size()){
                X=p[now].x-0.1;
                for(solid y:del[now]){
                    auto it=s.find(y);
                    s.erase(it);
                }
            }
            if(ins[now].size()){
                X=p[now].x+0.1;
                for(solid y:ins[now]){
                    s.insert(y);
                }
            }
            if(qs[now].size()){
                X=p[now].x;
                for(solid y:qs[now]){
                    bian tmp=bian(0,p[y].y,233);
                    auto it=s.upper_bound(tmp);
                    if(it==s.end()){
                        in[y]=inf;
                    }else{
                        in[y]=be[(*it).id];
                    }
                }
            }
        }
        for(reg i=1;i<=q;++i){
            int x=in[qa[i]];
            int y=in[qb[i]];
            if(x==inf||y==inf){
                puts("-1");
            }else if(x==y){
                puts("0");
            }else{
                printf("%d
    ",query(x,y));
            }
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */
    View Code
  • 相关阅读:
    4.计算机启动过程的简单介绍 计算机启动流程 计算机BIOS作用 POST 开机自检 计算机启动顺序 分区表 操作系统启动
    3.操作系统简单介绍 操作系统发展历史 批处理分时系统 操作系统是什么 操作系统对文件的抽象 进程 虚拟内存是什么 操作系统作用 操作系统功能
    2.计算机组成-数字逻辑电路 门电路与半加器 异或运算半加器 全加器组成 全加器结构 反馈电路 振荡器 存储 D T 触发器 循环移位 计数器 寄存器 传输门电路 译码器 晶体管 sram rom 微处理 计算机
    1.计算机发展阶段 计算机发展历史 机械式计算机 机电式计算机 电子计算机 逻辑电路与计算机 二极管 电子管 晶体管 硅 门电路 计算机 电磁学计算机二进制
    如何解决svn清理失败 不能更新 cleanup失败 cleanup乱码 更新乱码 svn更新提示清理 清理乱码不能清理 svn故障修复SVN cleanup 陷入死循环 svn cleanup时遇到错误怎么办
    eclipse svn插件卸载 重新安装 Subclipse卸载安装 The project was not built since its build path is incomplete This client is too old to work with the working copy at
    java for循环里面执行sql语句操作,有效结果只有一次,只执行了一次sql mybatis 循环执行update生效一次 实际只执行一次
    windows资源管理器多标签打开 windows文件夹多标签浏览 浏览器tab页面一样浏览文件夹 clover win8 win10 报错 无响应问题怎么解决 clover卡死 clover怎么换皮肤
    批处理启动vm虚拟机服务 vm12启动无界面启动vm虚拟机系统 windows上如何操作服务 sc net启动关闭服务
    不能ssh连接ubuntu linux 服务器 secureCRT不能ssh连接服务器 不能远程ssh连接虚拟机的ubuntu linux
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10898517.html
Copyright © 2020-2023  润新知