codeforces 1284 E

Not write code. . Forget the scanning line plus s = max (i, s) up
and did not transfer out. . . . .
Retired more than two months, the feeling turned into a mouth (((

I think the idea is very good, which is also the general line by scanning it.

My idea:
Consider "castle" this thing,
we found that if a triangle + the middle of a point, then as long as we then just add a point on the ok
is the "triangle containing a point." * (N-4)
Consider computing a number of triangular points are contained,
so hard. Let us count as one point is not how many triangles contain simple.
For a scan line, as long as we select two points on one side of it, then this is a triangle that does not contain the center point,
then we (n-1,3) by subtracting the triangle does not contain C can be obtained comprising a triangle.

Then included in the triangle * (n-4)

Test sample, Hey, just are twice as large, so weDivided by two direct submission
Draw a map,
found that indeed is the case, no matter how put four points, intermediate points will be counted in two triangles, so the contribution divided by 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;
}

Guess you like

Origin www.cnblogs.com/MXang/p/12152413.html