Amphiphilic Carbon Molecules
http://fastvj.rainng.com/contest/304637#problem/A
保存个极角排序的板子。
极角排序有两种。一种是atan2,速度快,但是有精度误差。另一种是叉积,速度慢但是只用进行整数运算。
注意用叉积极角排序的时候,要把上半区和下半区分开来排,而且每个点所在的半区要唯一。
struct point{
int x, y, c;
double rad;//atan2(y, x)
bool operator < (const point &t) const {return rad < t.rad;}
int getP() {return y > 0 || (y == 0 && x >= 0);}
}a[maxn];
int cross(point a, point b) {return a.x * b.y - a.y * b.x;}
bool cmp(point a, point b)
{
if (a.getP() == b.getP()) return cross(a, b) > 0;
else return a.getP() > b.getP();
}
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 5, inf = 0x3f3f3f3f;
struct point{
int x, y, c;
double rad;//atan2(y, x)
bool operator < (const point &t) const {return rad < t.rad;}
int getP() {return y > 0 || (y == 0 && x >= 0);}
}a[maxn];
int cross(point a, point b) {return a.x * b.y - a.y * b.x;}
bool cmp(point a, point b)
{
if (a.getP() == b.getP()) return cross(a, b) > 0;
else return a.getP() > b.getP();
}
vector<point> vp;
int main()
{
//ios::sync_with_stdio(0); cin.tie(0);
int n;
while (cin >> n){
if (n == 0) break;
if (n == 1 || n == 2){
cout << 2 << '\n';
continue;
}
for (int i = 0; i < n; ++i) cin >> a[i].x >> a[i].y >> a[i].c;
int ans = 0;
for (int i = 0; i < n; ++i){
//枚举点,极角排序
for (int j = 0; j < n; ++j){
if (i == j) continue;
//神级技巧啊,把黑点转化为对称的白点,这样就只用统计数量就可以了
if (a[j].c) vp.push_back(point{-(a[j].x - a[i].x), -(a[j].y - a[i].y), a[j].c, atan2(-(a[j].y - a[i].y), -(a[j].x - a[i].x))});
else vp.push_back(point{a[j].x - a[i].x, a[j].y - a[i].y, a[j].c, atan2(a[j].y - a[i].y, a[j].x - a[i].x)});
}
sort(vp.begin(), vp.end(), cmp);
//神级技巧2,尺取法模拟扫描线
//起手是2是因为枚举了一个点,然后从第一个点开始扫
int l = 0, r = 0, cnt = 2, sz = vp.size();
while (l < sz){
if (r == l) ++cnt, r = (r + 1) % sz;
while (r != l && cross(vp[l], vp[r]) >= 0) ++cnt, r = (r + 1) % sz;
++l, --cnt;
ans = max(ans, cnt);
}
vp.clear();
}
cout << ans << '\n';
}
return 0;
}
CODECHEF – Red and blue points
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e3 + 5, inf = 2e9 + 10;
struct point{
//注意爆int
ll x, y, c;
double rad;//atan2(y, x)
bool operator < (const point &t) const {return rad < t.rad;}
ll getP() {return y > 0 || (y == 0 && x >= 0);}
}a[maxn];
ll cross(point a, point b) {return a.x * b.y - a.y * b.x;}
bool cmp(point a, point b)
{
if (a.getP() == b.getP()) return cross(a, b) > 0;
else return a.getP() > b.getP();
}
vector<point> vp;
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
int t;
cin >> t;
while (t--){
int n, m;
cin >> n >> m;
for (int i = 0; i < n; ++i){
cin >> a[i].x >> a[i].y;
a[i].c = 0;
}
for (int i = n; i < n + m; ++i){
cin >> a[i].x >> a[i].y;
a[i].c = 1;
}
int ans = inf;
for (int i = 0; i < n + m; ++i){
for (int j = 0; j < n + m; ++j){
if (i == j) continue;
vp.push_back(point{a[j].x - a[i].x, a[j].y - a[i].y, a[j].c, atan2(a[j].y - a[i].y, a[j].x - a[i].x)});
}
sort(vp.begin(), vp.end(), cmp);
int l = 0, r = 0, g0 = 0, g1 = 0, c0 = 0, c1 = 0, sz = vp.size();
if (a[i].c == 0) g0 = 1;
else g1 = 1;
while (l < sz){
if (r == l){
if (vp[r].c == 0) ++g0;
else ++g1;
r = (r + 1) % sz;
}
while (r != l && cross(vp[l], vp[r]) > 0){
if (vp[r].c == 0) ++c0;
else ++c1;
r = (r + 1) % sz;
}
ans = min(ans, c0 + m - c1 - g1);
ans = min(ans, c1 + n - c0 - g0);
if (vp[l].c == 0) --g0;
else --g1;
++l;
//l != r的时候才要清,否则r就少算一次
if (l != r){
if (vp[l].c == 0) --c0, ++g0;
else --c1, ++g1;
}
}
vp.clear();
}
cout << ans << endl;
}
return 0;
}
又有极角排序了。
https://cn.vjudge.net/contest/319435#problem/J
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 1600;
struct point{
ll x, y;
int getP() {return y > 0 || (y == 0 && x >= 0);}
}a[maxn], ta[maxn];
ll cross(point a, point b) {return a.x * b.y - a.y * b.x;}
bool cmp(point a, point b)
{
if (a.getP() == b.getP()) return cross(a, b) > 0;
else return a.getP() > b.getP();
}
ll dis2(point a, point b)
{
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
ll yu(point a, point b, point c)
{
ll da = dis2(a, b), db = dis2(a, c), dc = dis2(b, c);
return da + db - dc;
}
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i].x >> a[i].y;
ll ans = 0;
for (int i = 1; i <= n; ++i){
int p = 0;
set<pii> sp;
for (int j = 1; j <= n; ++j){
if (i == j) continue;
ta[p].x = a[j].x - a[i].x;
ta[p].y = a[j].y - a[i].y;
sp.insert(pii(ta[p].x, ta[p].y));
++p;
}
sort(ta, ta + p, cmp);
int l = 0, r = 0;
point zx = point{0, 0};
while (l < p){
if (r == l) r = (r + 1) % p;
while (r != l && yu(zx, ta[l], ta[r]) > 0) r = (r + 1) % p;
while (r != l && yu(zx, ta[l], ta[r]) == 0){
if (sp.count(pii(ta[l].x + ta[r].x, ta[l].y + ta[r].y)))
ans = max(ans, (ll)(sqrt(dis2(zx, ta[l])) * sqrt(dis2(zx, ta[r])) + 0.5));
r = (r + 1) % p;
}
++l;
}
}
cout << ans << endl;
return 0;
}