1. 程式人生 > >2017 Russian Code Cup (RCC 17), Elimination Round D - Acute Triangles

2017 Russian Code Cup (RCC 17), Elimination Round D - Acute Triangles

D - Acute Triangles

思路:

極角排序+點積叉積

在一個三角形中,如果它是直角或者頓角三角形,那麼直角和頓角只會出現一次

所以直角和頓角三角形的個數等於直角和頓角的個數

所以銳角三角形的個數等於三元組個數減去直角和頓角的個數

三點共線看成退化的頓角三角形

怎麼算直角和頓角個數呢, 先按某個點極角排序,然後暴力過取,用雙指標維護到

當前幅角距離為pi/2 到 3*pi/2 的區間, 區間內點的個數就是到當前幅角為直角或頓角的個數

可以用點積和叉積分別判斷角度和相對方向

程式碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma
GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pi acos(-(long double)1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define
pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<long double, long double> #define mem(a, b) memset(a, b, sizeof(a)) #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); //
head const int N = 2e3 + 5; struct point { LL x, y; point(){} point(LL x, LL y):x(x), y(y){} LL dot(point p) { return x*p.x + y*p.y; } LL cross(point p) { return x*p.y - y*p.x; } }p[N], t[N]; bool anglecmp(point a, point b) { if(a.y <= 0 && b.y > 0) return true; if(a.y > 0 && b.y <= 0) return false; if(!a.y && !b.y) return a.x < b.x; return a.cross(b) > 0; } bool acute(point a, point b) { return a.dot(b) > 0 && a.cross(b) >= 0; } bool acute2(point a, point b) { return a.dot(b) > 0 && a.cross(b) < 0; } int main() { int T, n; scanf("%d", &T); while(T--) { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%lld %lld", &p[i].x, &p[i].y); LL ans = 1LL*n*(n-1)*(n-2)/6; for (int i = 1; i <= n; i++) { int cnt = 0; for (int j = 1; j <= n; j++) { if(j!=i) t[++cnt] = point(p[j].x - p[i].x, p[j].y - p[i].y); } sort(t+1, t+1+cnt, anglecmp); int l = 1, r = 1; for (int j = 1; j <= cnt; j++) { while(l <= cnt && acute(t[j], t[l])) l++; while(r <= cnt && !acute2(t[j], t[r])) r++; ans -= r-l; } } printf("%lld\n", ans); } return 0; }