zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    vue --- 全局弹窗,只调用对应实例
    代理相关;win操作
    mongoBD + node + express
    菜鸟初学 node 推荐 亲测easy
    H5 ---- 点击遍历所有标签,复制对应的文本
    async与await初步应用
    C# Enum 添加自定义Attribute,然后通过泛型与反射的方式得到事先定义的标记
    VS2013 C# 调用 cognex 的QuickBuild做程序时发生一个错误
    C# 获取数组的内存地址
    利用反射插入数据库与更新数据库
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10898517.html
Copyright © 2011-2022 走看看