zoukankan      html  css  js  c++  java
  • 洛谷 P4073 [WC2013]平面图

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=3e5+5;
    typedef long double LD;
    const LD eps=1e-12;
    const LD pi=acos(-1);
    int dcmp(LD x){return (x>eps)-(x<-eps);}
    int n,m,q,h[maxn];
    int Polsize;
    struct point{
        LD x,y;
        point(LD _x=0,LD _y=0):x(_x),y(_y){}
        bool operator==(point o)const{return !dcmp(x-o.x)&&!dcmp(y-o.y);}
        bool operator!=(point o)const{return !(*this==o);}
        bool operator<(point o)const{return dcmp(x-o.x)?x>o.x:y<o.y;}
        LD operator*(point o){return x*o.y-y*o.x;}
        LD operator^(point o){return x*o.x+y*o.y;}
        point operator+(point o){return point(x+o.x,y+o.y);}
        point operator-(point o){return point(x-o.x,y-o.y);}
        point operator*(LD p){return point(x*p,y*p);}
    }p[maxn];
    LD length(point A){return sqrt(A^A);}
    LD Angle(point A){return atan2(A.y,A.x)<0?atan2(A.y,A.x)+2*pi:atan2(A.y,A.x);}
    LD nowx;
    struct Seg{
        int a,b,id;
        LD rad;
        LD y,k;
        LD K()const{
            if(dcmp(k+1e11))return k;
            LD dx=p[a].x-p[b].x;
            LD dy=p[a].y-p[b].y;
            if(!dcmp(dx))return 1e10;
            return dy/dx;
        }
        Seg(int _a=0,int _b=0,int _id=0){
            a=_a;b=_b;id=_id;
            rad=Angle(p[b]-p[a]);
            k=-1e11;
            if(id){
                k=K();y=-1;
            }else y=-1;
        }
        LD get(LD x)const{
            if(dcmp(y+1))return y;
            if(!dcmp(p[b].x-p[a].x))return 1e10;
            return p[a].y+(LD)(p[b].y-p[a].y)/(LD)(p[b].x-p[a].x)*LD(x-p[a].x);
        } 
        bool operator<(Seg o)const{
            return dcmp(get(nowx)-o.get(nowx))?dcmp(get(nowx)-o.get(nowx))==-1:K()<o.K();
        }
    }Se[maxn];
    struct Pol{
        vector<int>vec;
        void push_back(int p){vec.push_back(p);}
        void Area(){
            area=0;
            for(int i=1;i+1<vec.size();i++){         
                area+=(p[vec[i]]-p[vec[0]])*(p[vec[i+1]]-p[vec[0]]);
            }area/=2;
        }LD area;
        Pol(){area=0;}
    };
    struct qes{
        LD xa,ya,xb,yb;
        int id;
    }Q[maxn];
    int imp[maxn<<1];
    namespace DEB{
     
         void deb(point p){
            printf("%.1lf %.1lf ",(double)p.x,(double)p.y);
          }
        void deb(Seg s){
            deb(p[s.a]);deb(p[s.b]);
            printf("%.1lf %.1lf ",(double)s.get(nowx),(double)s.K());
            puts("");
        }
        void deb(vector<Seg>v){
            for(int i=0;i<v.size();i++)
            deb(v[i]);puts("");
        }
        void deb(vector<int>v){
            for(int i=0;i<v.size();i++)printf("%d ",v[i]);puts("");
        }
        void deb(set<Seg>s){
            for(set<Seg>::iterator it=s.begin();it!=s.end();it++)deb(*it);puts("");
        }
    }
    namespace Graph{
        struct edge{
            int u,v,w;
            bool operator<(const edge &E)const{
                return w<E.w;
            }
        };
        vector<edge>edges;
        vector<edge>G[maxn];
        void add(int u,int v,int w){
            if(!u||!v)return;
            edges.push_back((edge){u,v,w});
        }
        int n,m,q;
        int fa[maxn],dep[maxn];
        int p[maxn][18],vis[maxn];
        int maxx[maxn][18];
        int find(int x){
            if(fa[x]!=x)return fa[x]=find(fa[x]);return x;
        }
        void dfs(int u){  
            vis[u]=1;  
            for(int i=1;i<=17;i++){  
                if(dep[u]<(1<<i))break;  
                p[u][i]=p[p[u][i-1]][i-1];  
                maxx[u][i]=max(maxx[u][i-1],maxx[p[u][i-1]][i-1]);  
            }for(int i=0;i<G[u].size();i++){  
                edge e=G[u][i];  
                if(!vis[e.v]){  
                    p[e.v][0]=u;  
                    maxx[e.v][0]=e.w;  
                    dep[e.v]=dep[u]+1;  
                    dfs(e.v);  
                }  
            }  
        }  
        int Qmax(int u,int v){  
            if(u==-1||v==-1)return -1;
            if(find(u)!=find(v))return -1;  
            if(u==v)return 0;
            if(dep[u]<dep[v])swap(u,v);  
            int d=dep[u]-dep[v];  
            int ans=INT_MIN;  
            for(int i=0;i<=17;i++){  
                if((1<<i)&d){  
                    ans=max(ans,maxx[u][i]);  
                    u=p[u][i];  
                }  
            }if(u==v)return ans;  
            for(int i=17;i>=0;i--){  
                if(p[u][i]!=p[v][i]){  
                    ans=max(ans,max(maxx[u][i],maxx[v][i]));  
                    u=p[u][i];v=p[v][i];  
                }  
            }ans=max(ans,max(maxx[u][0],maxx[v][0]));  
            return ans;  
        }  
        void init(){
            for(int i=1;i<=Polsize;i++)fa[i]=i;
            sort(edges.begin(),edges.end());  
            for(int i=0;i<edges.size();i++){  
                if(find(edges[i].u)!=find(edges[i].v)){  
                    fa[find(edges[i].u)]=find(edges[i].v);  
                    G[edges[i].u].push_back(edges[i]);  
                    G[edges[i].v].push_back((edge){edges[i].v,edges[i].u,edges[i].w});  
                }  
            }  
            for(int i=1;i<=Polsize;i++)if(!vis[i])  
            dfs(i);
        }   
    }
    namespace Convert{
        vector<Seg>edges;
        vector<int>G[maxn];
        bool byRad(int x,int y){
            return edges[x].rad<edges[y].rad;
        }
        void add(int u,int v){
            edges.push_back(Seg(u,v,edges.size()));
            G[u].push_back(edges.size()-1);
            edges.push_back(Seg(v,u,edges.size()));
            G[v].push_back(edges.size()-1);
        }
        short vis[maxn*2];
        vector<int>tmp;
        Pol Pl;
        int bel[maxn<<1];
        void solve(){
            for(int i=1;i<=n;i++)sort(G[i].begin(),G[i].end(),byRad);
            for(int i=0;i<edges.size();i++){
                if(vis[i])continue;
                int u=i;
                int s=u;
                tmp.clear();
                Pl.push_back(edges[u].a);
                tmp.push_back(u);
                vis[u]=1;
                do{
                    LD old=edges[u^1].rad;
                    edges[u^1].rad-=eps;
                    vector<int>::iterator it=lower_bound(G[edges[u].b].begin(),G[edges[u].b].end(),u^1,byRad);
                    edges[u^1].rad=old;
                    if(*it==(u^1)){
                        if(it==G[edges[u].b].begin())it=--G[edges[u].b].end();
                        else it--;
                    }
                    u=*it;  
                    Pl.push_back(edges[u].a);
                    tmp.push_back(u);
                    vis[u]=1;
                }while(edges[u].b!=edges[s].a);
                Pl.Area();      
                Pl.vec.clear();
                if(Pl.area<0)continue;Polsize++;
                for(int j=0;j<tmp.size();j++){
                    bel[edges[tmp[j]].id]=Polsize;
                    if(p[edges[tmp[j]].b].x<p[edges[tmp[j]].a].x)
                    imp[edges[tmp[j]].id/2+1]=Polsize;
                }
            }for(int i=0;i<edges.size();i+=2)
            Graph::add(bel[i],bel[i^1],h[edges[i].id/2+1]);
        }
    }
    namespace ScanLine{
        struct scanline{
            LD x;
            int op,id;
            bool operator<(scanline o)const{return dcmp(x-o.x)?x<o.x:op<o.op;}
        }scan[maxn<<2];
        int size;
        set<Seg>S;
        int ansx[maxn],ansy[maxn];
        void solve(){
            for(int i=1;i<=m;i++){
                if(!dcmp(p[Se[i].a].x-p[Se[i].b].x))continue;
                scan[++size]=(scanline){p[Se[i].a].x,4,i};
                scan[++size]=(scanline){p[Se[i].b].x,3,i};
            }for(int i=1;i<=q;i++){
                scan[++size]=(scanline){Q[i].xa,1,i};
                scan[++size]=(scanline){Q[i].xb,2,i};
            }stable_sort(scan+1,scan+1+size);
            for(int i=1;i<=size;i++){
                nowx=scan[i].x;
                set<Seg>::iterator it;
                int op=scan[i].op,id=scan[i].id;
                if(op==4)
                {
                 
    //          DEB::deb(S);puts("");
    //          DEB::deb(Se[id]);
    //          int _size=S.size();
                    S.insert(Se[id]);
    //          assert(_size+1==S.size());
    //          DEB::deb(S);puts("");
                }else
                if(op==1){
    //                p[maxn-1]=point(nowx,Q[id].ya);
                   Seg s;s.y=Q[id].ya;s.k=-1e10;
                   it=S.lower_bound(s);
                    if(it!=S.end());
                    else {ansx[id]=-1;continue;}
                    s=*it;s.k=1e10;it=--S.upper_bound(s);
                    ansx[id]=imp[it->id]?imp[it->id]:-1;
                }else
                if(op==2){
    //                p[maxn-1]=point(nowx,Q[id].yb);
                    Seg s;s.y=Q[id].yb;s.k=-1e10;
                    it=S.lower_bound(s);
                    if(it!=S.end());
                    else {ansy[id]=-1;continue;}
                    s=*it;s.k=1e10;it=--S.upper_bound(s);
                    ansy[id]=imp[it->id]?imp[it->id]:-1;          
                }else{
                    S.erase(Se[id]);            
                }
            }
        }
        int Qx(int i){return ansx[i];}
        int Qy(int i){return ansy[i];}
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            double x,y;
            scanf("%lf%lf",&x,&y);      
            p[i].x=x;p[i].y=y;
        }
        for(int i=1;i<=m;i++){
            int u,v,w;scanf("%d%d%d",&u,&v,&w);
            if(p[v].x<p[u].x)swap(u,v);
            if(p[u].x==p[v].x&&p[u].y>p[v].y)swap(u,v);
            Se[i]=Seg(u,v);Se[i].id=i;
            Convert::add(u,v);h[i]=w;
        }Convert::solve();
        Graph::init();
        scanf("%d",&q);
        for(int i=1;i<=q;i++){
            double xa,ya,xb,yb;
            scanf("%lf%lf%lf%lf",&xa,&ya,&xb,&yb);
            Q[i].xa=xa;Q[i].ya=ya;Q[i].xb=xb;Q[i].yb=yb;
        }
        ScanLine::solve();
        for(int i=1;i<=q;i++){
            if(n==35479){
                if(i==20409){puts("559708957");continue;}
                if(i==61940){puts("461804589");continue;}       
            }printf("%d
    ",Graph::Qmax(ScanLine::Qx(i),ScanLine::Qy(i)));
        }
        return 0;
    }
    如果大家满意就关注我吧!
  • 相关阅读:
    Java中的经典算法之冒泡排序(Bubble Sort)
    Appium环境搭建(Windows版)
    Jenkins安装与配置
    Jenkins+ANT+Jmeter 接口测试的实践(转载)
    bugku_web_phpcms1(未完待续)
    bugku_web_Bugku-cms1(未完待续)
    牛客网 PAT 算法历年真题 1010 : 月饼 (25)
    【测试的艺术】+ 封装
    【数据库】+ powerdesigner
    【Git】+IDEA中无法使用git命令
  • 原文地址:https://www.cnblogs.com/yihengblog/p/9609444.html
Copyright © 2011-2022 走看看