codeforces 1284 E

不会写代码了。。扫描线忘记加 s = max(i,s) 了
然后没调出来。。。。。
退役两个多月了,感觉变成一张嘴了(((

思路还是很好想的,这也就一般通过扫描线吧。

我的思路:
考虑『 castle 』这个东西,
我们发现,如果是 三角形+中间一个点的话, 那么我们只要再随便加一个点就ok了
也就是『三角形包含一个点』*(n-4)
考虑计算 一个点被多少个三角形包含,
好难。 我们不如算 一个点 不被多少个三角形包含,简单。
对于一条扫描线,我们只要在它一侧选出两个点,那么这就是一个不包含 中心点的三角形了,
然后我们用C(n-1,3)减去不包含的三角形就能得到包含的三角形了。

然后用包含的三角形*(n-4)

测样例,咦,刚好都大了两倍,所以我们直接除以二提交
画个图,
发现确实是这样,不管四个点怎么放,中间的点都会被算进两个三角形里,所以贡献除以2

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct point{
    ll x,y,id;
    point operator +(const point & k1)const {return (point){k1.x+x,k1.y+y};}
    point operator -(const point & k1)const {return (point){x-k1.x,y-k1.y};}
    inline int getP()const {return y>0||(y==0&&x<0);}
};
inline ll cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
inline ll dot(point k1,point k2){ return k1.x*k2.x+k1.y*k2.y;}
inline int compareangle(point k1,point k2){
    return k1.getP()<k2.getP()||(k1.getP()==k2.getP()&&cross(k1,k2)>0);
}
ll n;
point p[2525];
ll slove(int id){//无三点共线
    //找不包含 id 的三角形
    vector<point> v;
    for(int i=1;i<=n;i++)if(i!=id)v.push_back(p[i]-p[id]);
    sort(v.begin(),v.end(),compareangle);
    int m = v.size();
//    for(auto x:v)cout<<x.x<<' '<<x.y<<endl;
    for(int i=0;i<m;i++)v.push_back(v[i]);
    ll res = 0;
    int s=0;
    for(int i=0;i<m;i++){
        point _180 = {-v[i].x,-v[i].y};
        s=max(i,s);
        while (s<i+m-1&&(cross(v[s+1],_180)>0&&cross(v[s+1],v[i])<0))s++;
        //s<180
        int cnt = s-i;
        res += 1ll*cnt*(cnt-1)/2;
    }
    ll sum = 1ll*(n-1)*(n-2)*(n-3)/6;
    sum-=res;//被多少个三角形包含
    return sum*(n-4);
}

int main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&p[i].x,&p[i].y);
    }
    ll ans = 0;
    for(int i=1;i<=n;i++){
//        cout<<slove(i)<<endl;
        ans+=slove(i);
    }
    cout<<ans/2<<endl;
}
posted @ 2020-01-05 14:37  MXang  阅读(206)  评论(0编辑  收藏  举报