NC53264. 两个人的星座
描述
输入描述
第一行一个整数N,代表展望台上能观测到的星星的数量。
接下来N行,第i行有三个空格分隔的整数,表示i号星的坐标为,表示i号星的颜色,其中0代表红色,1代表蓝色,2代表黄色。
输出描述
输出一行一个整数,表示JOIOI座候补的方案数。
示例1
输入:
7 0 0 0 2 0 1 1 2 2 -2 1 0 -2 -3 0 0 -2 1 2 -2 2
输出:
4
说明:
示例2
输入:
8 16 0 0 17 0 0 0 7 2 0 -7 2 -1 -1 1 -1 1 2 -6 4 1 -6 -4 1
输出:
12
示例3
输入:
21 1 20 0 4 20 0 0 22 0 5 22 0 6 25 0 8 25 0 4 26 0 11 11 1 7 12 1 14 13 1 8 15 1 15 16 1 11 17 1 18 0 2 13 2 2 16 2 2 19 4 2 18 6 2 21 8 2 24 8 2 19 10 2
输出:
7748
C++(g++ 7.5.0) 解法, 执行用时: 1181ms, 内存消耗: 884K, 提交时间: 2022-10-19 20:27:37
#include<bits/stdc++.h> using namespace std; using ll = long long; constexpr ll eps = 0; struct point{ ll x,y; friend bool operator !=(const point &lhs, const point &rhs){ return abs(lhs.x-rhs.x)+abs(lhs.y-rhs.y) > eps; } friend point operator +(const point &lhs, const point &rhs) { return {lhs.x+rhs.x, lhs.y+rhs.y}; } friend point operator -(const point &lhs, const point &rhs) { return {lhs.x-rhs.x, lhs.y-rhs.y}; } friend point operator *(const ll &k, const point &t){ return {k*t.x, k*t.y}; } friend ll operator *(const point &lhs, const point & rhs) { return lhs.x*rhs.y - lhs.y*rhs.x; } }; using ppi = pair<point, int>; bool argcmp (const point &a, const point &b) { const auto quad = [](const point &a) { if(a.y < -eps) return 3; if(a.y > eps) return 1; if(a.x < -eps) return 2; if(a.x > eps) return 0; return 0; }; const int qa = quad(a), qb = quad(b); if(qa != qb) return qa < qb; return a*b > eps; }; void solve(){ int n; cin >> n; vector<ppi>vec(n); int n0 = 0, n1 = 0, n2 = 0; for(int i = 0 ; i < n ; i ++){ auto &[p,c] = vec[i]; cin >> p.x >> p.y >> c; if(c==0) n0++; else if(c==1) n1++; else if(c==2) n2++; } ll ans = 0; auto solve = [&](const point &p, const int &c0)->void{ vector<ppi>tmp; for(auto &[q,c]: vec){ if(q != p) tmp.push_back({q-p, c}); } sort(tmp.begin(), tmp.end(), [](ppi &A, ppi &B){ return argcmp(A.first, B.first); }); auto copy = tmp; tmp.insert(tmp.end(), copy.begin(), copy.end()); int t0 = 0, t1 = 0, t2 = 0; int m = tmp.size()/2; for(int i = 0, j = 0; i < m && (tmp[i].first.y > eps || i==0) ; i ++){ auto &[p1,c1] = tmp[i]; if(c1==0) t0--; else if(c1==1) t1--; else t2--; while(j<i+m && p1 * tmp[j].first >= 0){ if(tmp[j].second==0) t0++; else if(tmp[j].second==1) t1++; else t2++; j++; } ll v1, v2, oc0=n0-t0, oc1=n1-t1, oc2=n2-t2; if(c0==0) v1 = t1*t2, oc0--; else if(c0==1) v1 = t0*t2, oc1--; else v1 = t0*t1, oc2--; if(c1==0) v2 = oc1 * oc2; else if(c1==1) v2 = oc0 * oc2; else v2 = oc0 * oc1; ans += v1 * v2; } }; for(auto &[p,c]: vec){ solve(p,c); } cout << ans << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(0); solve(); return 0; }
C++11(clang++ 3.9) 解法, 执行用时: 1277ms, 内存消耗: 600K, 提交时间: 2020-08-03 20:51:32
#include<bits/stdc++.h> #define ts cout<<"ok"<<endl #define ll long long #define hh puts("") using namespace std; int n,cnt[2][3],to[3005]; ll ans; double PI=3.14159265358979323846; struct point{ double x,y,k; int col; }a[3005],t[3005]; inline int read(){ int ret=0,ff=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') ff=-1;ch=getchar();} while(isdigit(ch)){ret=(ret<<3)+(ret<<1)+(ch^48);ch=getchar();} return ret*ff; } point operator - (point A,point B){ return (point){A.x-B.x,A.y-B.y}; } inline bool cmp(point A,point B){ return A.k<B.k; } inline ll calc(int x,int col){ if(col==0) return 1ll*cnt[x][1]*cnt[x][2]; else if(col==1) return 1ll*cnt[x][0]*cnt[x][2]; else if(col==2) return 1ll*cnt[x][0]*cnt[x][1]; } signed main(){ n=read(); for(int i=1;i<=n;i++){ a[i].x=read(); a[i].y=read(); a[i].col=read(); } for(int i=1;i<=n;i++){ int tot=0; for(int j=1;j<=n;j++){ if(j==i) continue; t[++tot]=a[j]; t[tot].k=atan2((a[j]-a[i]).y,(a[j]-a[i]).x); if(t[tot].k<=0) t[tot].k+=PI; } memset(cnt,0,sizeof(cnt)); sort(t+1,t+tot+1,cmp); for(int j=1;j<=tot;j++){ if(t[j].y<a[i].y||(t[j].y==a[i].y&&t[j].x>a[i].x)) to[j]=0,cnt[0][t[j].col]++; else to[j]=1,cnt[1][t[j].col]++; } for(int j=1;j<=tot;j++){ cnt[to[j]][t[j].col]--; ans+=calc(0,t[j].col)*calc(1,a[i].col)+calc(0,a[i].col)*calc(1,t[j].col); to[j]^=1; cnt[to[j]][t[j].col]++; } } printf("%lld\n",ans>>2); return 0; }