• bzoj4814: [Cqoi2017]小Q的草稿


    Description

    小Q是个程序员。众所周知,程序员在写程序的时候经常需要草稿纸。小Q现在需要一张草稿纸用来画图,但是桌上
    只有一张草稿纸,而且是一张被用过很多次的草稿纸。草稿纸可以看作一个二维平面,小Q甚至已经给它建立了直
    角坐标系。以前每一次草稿使用过的区域,都可以近似的看作一个平面上的一个三角形,这个三角形区域的内部和
    边界都不能再使用。当然了,以前的草稿也没有出现区域重叠的情况。小Q已经在草稿纸上画上了一些关键点,这
    些关键点都在没使用过的区域。小Q想把这些关键点两两之间尽可能的用线段连接起来。连接两个关键点的线段有
    可能会穿过已经用过的草稿区域,这样显然不允许。于是小Q就想知道,有多少对关键点可以被线段连接起来,而
    且还不会穿过已经用过的区域。为了方便,小Q保证任意三个关键点不会共线。

    Input

    第一行包含两个整数V,T,表示草稿纸上的关键点数量和三角形区域数量。
    接下来V行,每行两个整数x,y,表示一个关键点的坐标(x,y)。
    接下来T行,每行六个整数x1,y1,x2,y2,x3,y3,表示一个三角形区域的三个顶点坐标分别是(x1,y1),(x2,y2),(x3,y
    3)保证三角形的面积大于0。
    V<=1000,T<=1000,0<=所有坐标<=10^8且为整数

    Output

    输出一行,一个整数,表示能够被线段连接起来的关键点有多少对。

    对每个点以它为中心进行扫描线,处理在右方的点和三角形。

    #include<bits/stdc++.h>
    typedef long long i64;
    typedef double ld;
    int n,m;
    int sgn(i64 x){return x<0?-1:x>0;}
    struct pos{
        int x,y;
        void R(){scanf("%d%d",&x,&y);}
        i64 pw2(){return i64(x)*x+i64(y)*y;}
    }ps[1007],ws[1007],trs[1007][3],O=(pos){0,0},now;
    pos operator-(const pos&a,const pos&b){return (pos){a.x-b.x,a.y-b.y};}
    int operator*(const pos&a,const pos&b){return sgn(i64(a.x)*b.y-i64(a.y)*b.x);}
    ld mul(const pos&a,const pos&b){return ld(a.x)*b.y-ld(a.y)*b.x;}
    bool cmp(const pos&a,const pos&b){return a.x!=b.x?a.x<b.x:a.y<b.y;}
    bool operator<(const pos&a,const pos&b){return a*b<0;}
    struct seg{
        pos a[2];
        ld val()const{return mul(a[0],a[1])/mul(now,a[1]-a[0]);}
        bool operator<(const seg&w)const{return val()<w.val();}
    };
    std::set<seg>st;
    std::set<seg>::iterator its[2007];
    struct Q{
        pos a[2];
        int t,id;
        bool operator<(const Q&w)const{
            int x=a[t]*w.a[w.t];
            return x?x<0:t<w.t;
        }
        bool operator<(const pos&w){
            int x=a[t]*w;
            return x?x<0:!t;
        }
        void cal(){
            now=a[t];
            if(cmp(now,O))now=(pos){0,1};
            if(t)st.erase(its[id]);
            else{
                seg s=(seg){a[0],a[1]};
                its[id]=st.insert(s).first;
            }
        }
    }qs[2007];
    bool cross(pos a,pos b1,pos b2){
        pos ba=b2-a;
        if((a*(b1-a))*(a*ba)>0)return 0;
        pos b3=b1-b2;
        return (b3*b2)*(b3*ba)<=0;
    }
    int ans=0,wp,qp,ip;
    void scl(){
        for(int i=0,j=0;i<wp;++i){
            for(;j<qp&&qs[j]<ws[i];qs[j++].cal());
            if(st.empty()||!cross(ws[i],st.begin()->a[0],st.begin()->a[1]))++ans;
        }
    }
    void aq(pos a,pos b){
        bool da=cmp(O,a),db=cmp(O,b);
        ++ip;
        if(da)qs[qp++]=(Q){a,b,0,ip};
        else if(db)((Q){a,b,0,ip}).cal();
        if(db)qs[qp++]=(Q){a,b,1,ip};
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)ps[i].R();
        std::sort(ps+1,ps+n+1,cmp);
        for(int i=1;i<=m;++i)for(int j=0;j<3;++j)trs[i][j].R();
        for(int i=1;i<=n;++i){
            st.clear();
            wp=0,qp=0,ip=0;
            for(int j=i+1;j<=n;++j)ws[wp++]=ps[j]-ps[i];
            std::sort(ws,ws+wp);
            for(int j=1;j<=m;++j){
                pos tr[3];
                for(int t=0;t<3;++t)tr[t]=trs[j][t]-ps[i];
                std::sort(tr,tr+3);
                aq(tr[0],tr[2]);
            }
            std::sort(qs,qs+qp);
            scl();
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Redis源代码分析(十三)--- redis-benchmark性能測试
    kvm中运行kvm
    umount.nfs device busy day virsh extend diskSpace, attachDisk
    ultravnc
    openNebula dubug
    maintenance ShellScripts
    virsh VMI deploy data serial xml
    cloud computing platform,virtual authentication encryption
    基于C 的libvirt 接口调用
    storage theory
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7337264.html
Copyright © 2020-2023  润新知