CF1284E New Year and Castle Construction

题面:https://codeforces.com/problemset/problem/1284/E
题解:
考虑一个五元组形成凸包的情况。
由于三点不共线,因此只可能有三种情况:
1.凸包含有3个点:此时贡献为2;
2.凸包含有4个点:贡献为1;
3.凸包含有5个点:贡献为0。
设这三种情况的个数分别为\(x_3\),\(x_4\),\(x_5\),
那么答案即为2\(x_3\)+\(x_4\)。
这个东西很不好求,考虑转化。
首先发现\(x_3\)+\(x_4\)+\(x_5\)=\(C(n,5)\)
其次,发现如果能求出3\(x_3\)+4\(x_4\)+5\(x_5\),
那答案就很容易求出。这个式子的几何意义即为
\(\sum\)每一条边所在的凸包数。
用双指针求出这个东西即可。
时间复杂度:O(\(n^2\)logn)
代码:

#include<bits/stdc++.h>
using namespace std;
#define re register ll
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline ll
#define STS system("pause")
template<class D>I read(D &res){
    res=0;register D g=1;register char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')g=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        res=(res<<3)+(res<<1)+(ch^48);
        ch=getchar();
    }
    res*=g;
}
typedef pair<ll,ll>pii;
struct Vec{
    ll x,y;
    Vec(ll _x=0,ll _y=0){x=_x;y=_y;}
    friend Vec operator + (Vec a,Vec b){return Vec(a.x+b.x,a.y+b.y);}
    friend Vec operator - (Vec a,Vec b){return Vec(a.x-b.x,a.y-b.y);}
    friend ll operator ^ (Vec a,Vec b){return a.x*b.y-a.y*b.x;}
    friend bool operator < (Vec a,Vec b){
        pii A=make_pair(a.x,a.y),B=make_pair(b.x,b.y);
        bool c=A<make_pair(0ll,0ll),d=B<make_pair(0ll,0ll);
        return c==d?(a^b)>=0:c<d;
    }
}p[2550];
vector<Vec>v;
ll n,m,ans,cnt;
IN C(ll x,ll y){
    re res=1;
    F(i,0,y-1){res*=(x-i);res/=(i+1);}
    return res;
}
int main(){
    read(n);
    F(i,1,n)read(p[i].x),read(p[i].y);
    F(i,1,n){
        v.clear();
        F(j,1,n){
            if(i==j)continue;
            v.emplace_back(p[j]-p[i]);
        }       
        sort(v.begin(),v.end());
        m=0;
        F(j,0,v.size()-1){
            while(m<j+v.size()&&(v[j]^v[m%v.size()])>=0)m++;
            cnt+=C(m-j-1,3);
        }
    }
    ans=C(n,5)*5ll-cnt;
    cout<<ans;
    return 0;
}
上一篇:.NetCore IOC容器练习


下一篇:Linux下不同平台下的代码转义字符不兼容问题(dos2unix的使用)