zoukankan      html  css  js  c++  java
  • 15-16 ICPC europe J Saint John Festival (graham扫描法+旋转卡壳)

    题意:给n个大点,m个小点$(n<=1e5,m<=5e5),问有多少个小点,存在3个大点,使小点在三个大点组成的三角形内。

    解题思路:

      首先,易证,若该小点在某三大点行成的三角形内,则该小点必然处在大点组成的凸包内。那么首先,现将大点形成的凸包计算出来,但是若对每个点进行暴力枚举,在最坏情况下,若凸包上点数太多并且脸黑不断找区间,复杂度会达到$O(nm)$,因此要对点是否在凸包内的判断过程进行优化。

      将凸包划分为若干个三角形,我们可以先将这m个待判断的点进行极角排序,排序后,极角较大的点要么处在较小的点的逆时针方向的三角形内要么在同一个三角形内,要么两个点在同一三角形内。因此在点坐标转移时,采用旋转卡壳,所在的三角形区域也逆时针选择即可。而对于小点是否在三角形内,采用面积判断即可,为了防止爆精度推荐用行列式计算面积,时间复杂度$O(nlogn+mlogm+m)$

      下面贴上AC代码。

      

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,ll> pii;
    #define rep(i,a,b) for(int i=a;i<b;i++)
    #define rept(i,a,b) for(int i=a;i<=b;i++)
    #define mes(a,b) memset(a,b,sizeof a)
    #define pb push_back
    #define dd(x) cout<<#x<<"="<<x<<" "
    #define de(x) cout<<#x<<"="<<x<<"
    "
    #define fi first
    #define se second
    #define mp make_pair
    pii point[10005],small[50005];
    pii operator -(const pii &s1,const pii &s2)
    {
        return mp(s1.fi-s2.fi,s1.se-s2.se);
    }
    int s[10005];
    ll chaji(const pii &s1,const pii &s2)
    {
        return s1.fi*s2.se-s1.se*s2.fi;
    }
    bool comp(const pii &s1,const pii &s2)
    {
        if((s1.se<point[0].se)+(s2.se<point[0].se)==1) return s1.se>s2.se;
        ll x=chaji(s1-point[0],s2-point[0]);
        if(x>0||(x==0&&abs(s1.fi-point[0].fi)<abs(s2.fi-point[0].fi))) return 1;
        else return 0;
    }
    ll sqare(const pii &a,const pii &b,const pii &c)
    {
        return abs( (b.fi-a.fi)*(c.se-a.se) -(c.fi-a.fi)*(b.se-a.se) );
    }
     
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,m;
        cin>>n;
        rep(i,0,n) cin>>point[i].fi>>point[i].se;
        int p=0;
        rep(i,1,n)
            if( point[i].se<point[p].se||(point[i].se==point[p].se&&point[i].fi<point[p].fi) )
                p=i;
        swap(point[0],point[p]);
        //dd(point[0].fi);de(point[0].se);
        sort(point+1,point+n,comp);
        int cnt=0;
        s[cnt++]=0;
        s[cnt++]=1;
        
        rep(i,2,n)
        {
            while(cnt>=2&&chaji(point[s[cnt-1]]-point[i],point[s[cnt-2]]-point[i])>=0) cnt--;
            s[cnt++]=i;
        }
        
        cin>>m;
        rep(i,0,m) cin>>small[i].fi>>small[i].se;
        sort(small,small+m,comp);
        int ans=0;
        p=1;
        
        int start=0;
        while(start<m&&chaji(small[start]-point[s[0]],point[s[1]]-point[s[0]])>0) start++;
        rep(i,start,m)
        {
            if(small[i].se<point[0].se) break;
            while(p<cnt-1&&chaji( small[i]-point[s[0]],point[s[p+1]]-point[s[0]] )<0 ) p++;
            if(p==cnt-1) break;
            if(chaji( small[i]-point[s[0]],point[s[p]]-point[s[0]] )==0 )
            {
                if((small[i].fi<point[s[0]].fi)+(small[i].fi<point[s[p]].fi)==1) ans++;
                continue;
            }
            else if(chaji( small[i]-point[s[0]],point[s[p+1]]-point[s[0]] )<0)
            {
                if((small[i].fi<point[s[0]].fi)+(small[i].fi<point[s[p+1]].fi)==1) ans++;
                continue;
            }
            if(sqare(point[s[0]],point[s[p]],point[s[p+1]])==sqare(point[s[0]],point[s[p]],small[i])+sqare(point[s[0]],point[s[p+1]],small[i])+sqare(point[s[p]],point[s[p+1]],small[i]))
                ans++;
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    [Algo] 306. Check If Linked List Is Palindrome
    [Algo] 42. Partition Linked List
    [Algo] 20. Search In Unknown Sized Sorted Array
    [LC] 1167. Minimum Cost to Connect Sticks
    [LC] 212. Word Search II
    安装oracle developer 10g 时报错,提示must be 5.0, 5.1, 5.2 or 6.1 . Actual 6.2
    APP-INV-05577
    客户化的并发程序出现黄条警告,并无法输出内容
    EBS Concurrent Manager(并发管理器)异常处理[final]【转】
    oracle 通过透明网关gateway 连接sqlserver
  • 原文地址:https://www.cnblogs.com/FZUzyz/p/11651598.html
Copyright © 2011-2022 走看看