总览:
随机化可过大部分题……
随机旋转坐标轴,按
x
x
x 排序,对每个点和后面几个点求距离,取最小
KDtree可做
分治是正常方法
将点按
x
x
x 排序,以中点为分治中心,递归处理
当合并时,发现对于
[
m
i
d
x
−
a
n
s
,
m
i
d
x
+
a
n
s
]
[mid_x-ans,mid_x+ans]
[midx−ans,midx+ans] 外的点,一定不优,可以排除
将中间的点按
y
y
y 排序,同理,
[
m
i
d
y
−
a
n
s
,
m
i
d
y
+
a
n
s
]
[mid_y-ans,mid_y+ans]
[midy−ans,midy+ans] 外的点不优,排除
对剩下的所有点两两求距离
T1 P1429 平面最近点对(加强版)
思路:
板子
代码:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
typedef unsigned long long ull;
typedef unsigned int uint;
#define pb push_back
#define mp make_pair
namespace IO {
char buf_[1 << 21], *p1_ = buf_, *p2_ = buf_;
#define ch() \
(p1_ == p2_ && \
(p2_ = (p1_ = buf_) + fread(buf_, 1, 1 << 21, stdin), p1_ == p2_) \
? EOF \
: *p1_++)
inline int in() {
int s = 0, f = 1;
char x = getchar();
for (; x < '0' || x > '9'; x = getchar())
if (x == '-') f = -1;
for (; x >= '0' && x <= '9'; x = getchar()) s = (s * 10) + (x & 15);
return f == 1 ? s : -s;
}
char _buf[1 << 21];
int _p1 = -1;
inline void flush() {
fwrite(_buf, 1, _p1 + 1, stdout);
_p1 = -1;
}
inline void pc(char x) {
if (_p1 == (1 << 21) - 1) flush();
_buf[++_p1] = x;
}
inline void out(int x) {
char k[30];
int pos = 0;
if (!x) {
pc('0');
return;
}
if (x < 0) {
pc('-');
x = -x;
}
while (x) {
k[++pos] = (x % 10) | 48;
x /= 10;
}
for (int i = pos; i; i--) pc(k[i]);
return;
}
inline void out(string x) {
int len = x.size();
for (int i = 0; i < len; i++) pc(x[i]);
}
} // namespace IO
using namespace IO;
const int A = 2e5 + 5;
const double INF = 1e15;
const double EPS = 1e-9;
const double pi = acos(-1);
inline int cp(double u, double v) {
if (fabs(u - v) < EPS) return 0;
return u > v ? 1 : -1;
}
int n;
struct Point {
double x, y;
Point(double u = 0, double v = 0) { x = u, y = v; }
inline friend Point operator+(Point u, Point v) {
return Point(u.x + v.x, u.y + v.y);
}
inline friend Point operator-(Point u, Point v) {
return Point(u.x - v.x, u.y - v.y);
}
inline friend Point operator*(Point u, double v) {
return Point(u.x * v, u.y * v);
}
inline friend Point operator/(Point u, double v) {
return Point(u.x / v, u.y / v);
}
inline friend double operator^(Point u, Point v) {
return u.x * v.y - u.y * v.x;
}
inline friend double operator&(Point u, Point v) {
return u.x * v.x + u.y * v.y;
}
inline friend bool operator==(Point u, Point v) {
return !cp(u.x, v.x) && !cp(u.y, v.y);
}
inline friend bool operator!=(Point u, Point v) { return !(u == v); }
inline friend bool operator<(Point u, Point v) {
if (cp(u.x, v.x)) return u.x < v.x;
return u.y < v.y;
}
} p[A];
inline double dis(Point u, Point v) {
return sqrt((u.x - v.x) * (u.x - v.x) + (u.y - v.y) * (u.y - v.y));
}
inline Point rotate(Point u, double phi) {
return Point(u.x * cos(phi) - u.y * sin(phi),
u.x * sin(phi) + u.y * cos((phi)));
}
double ans;
inline void work(double phi) {
for (int i = 1; i <= n; i++) p[i] = rotate(p[i], phi);
sort(p + 1, p + 1 + n);
for (int i = 1; i < n; i++)
for (int j = 1; i + j <= n && j <= 5; j++)
ans = min(ans, dis(p[i], p[i + j]));
return;
}
signed main() {
srand(time(0));
n = in();
ans = INF;
for (int i = 1; i <= n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
for (int i = 1; i <= 20; i++) work((rand() % 360) / 180.0 * pi);
printf("%0.4lf\n", ans);
flush();
return 0;
}
T2 P6247 [SDOI2012]最近最远点对
思路:
最远点对随机到最远的点就行
代码:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
typedef unsigned long long ull;
typedef unsigned int uint;
#define pb push_back
#define mp make_pair
namespace IO {
char buf_[1 << 21], *p1_ = buf_, *p2_ = buf_;
#define ch() \
(p1_ == p2_ && \
(p2_ = (p1_ = buf_) + fread(buf_, 1, 1 << 21, stdin), p1_ == p2_) \
? EOF \
: *p1_++)
inline int in() {
int s = 0, f = 1;
char x = getchar();
for (; x < '0' || x > '9'; x = getchar())
if (x == '-') f = -1;
for (; x >= '0' && x <= '9'; x = getchar()) s = (s * 10) + (x & 15);
return f == 1 ? s : -s;
}
char _buf[1 << 21];
int _p1 = -1;
inline void flush() {
fwrite(_buf, 1, _p1 + 1, stdout);
_p1 = -1;
}
inline void pc(char x) {
if (_p1 == (1 << 21) - 1) flush();
_buf[++_p1] = x;
}
inline void out(int x) {
char k[30];
int pos = 0;
if (!x) {
pc('0');
return;
}
if (x < 0) {
pc('-');
x = -x;
}
while (x) {
k[++pos] = (x % 10) | 48;
x /= 10;
}
for (int i = pos; i; i--) pc(k[i]);
return;
}
inline void out(string x) {
int len = x.size();
for (int i = 0; i < len; i++) pc(x[i]);
}
} // namespace IO
using namespace IO;
const int A = 2e5 + 5;
const double INF = 1e15;
const double EPS = 1e-9;
const double pi = acos(-1);
inline int cp(double u, double v) {
if (fabs(u - v) < EPS) return 0;
return u > v ? 1 : -1;
}
int n;
struct Point {
double x, y;
Point(double u = 0, double v = 0) { x = u, y = v; }
inline friend Point operator+(Point u, Point v) {
return Point(u.x + v.x, u.y + v.y);
}
inline friend Point operator-(Point u, Point v) {
return Point(u.x - v.x, u.y - v.y);
}
inline friend Point operator*(Point u, double v) {
return Point(u.x * v, u.y * v);
}
inline friend Point operator/(Point u, double v) {
return Point(u.x / v, u.y / v);
}
inline friend double operator^(Point u, Point v) {
return u.x * v.y - u.y * v.x;
}
inline friend double operator&(Point u, Point v) {
return u.x * v.x + u.y * v.y;
}
inline friend bool operator==(Point u, Point v) {
return !cp(u.x, v.x) && !cp(u.y, v.y);
}
inline friend bool operator!=(Point u, Point v) { return !(u == v); }
inline friend bool operator<(Point u, Point v) {
if (cp(u.x, v.x)) return u.x < v.x;
return u.y < v.y;
}
} p[A];
inline double dis(Point u, Point v) {
return sqrt((u.x - v.x) * (u.x - v.x) + (u.y - v.y) * (u.y - v.y));
}
inline Point rotate(Point u, double phi) {
return Point(u.x * cos(phi) - u.y * sin(phi),
u.x * sin(phi) + u.y * cos((phi)));
}
double ans1, ans2;
inline void work(double phi) {
for (int i = 1; i <= n; i++) p[i] = rotate(p[i], phi);
sort(p + 1, p + 1 + n);
for (int i = 1; i < n; i++) {
for (int j = 1; i + j <= n && j <= 5; j++)
ans1 = min(ans1, dis(p[i], p[i + j]));
for (int j = 1; n - j + 1 > i && j <= 5; j++)
ans2 = max(ans2, dis(p[i], p[n - j + 1]));
}
return;
}
signed main() {
srand(time(0));
n = in();
ans1 = INF, ans2 = -INF;
for (int i = 1; i <= n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
for (int i = 1; i <= 20; i++) work((rand() % 360) / 180.0 * pi);
printf("%0.2lf %0.2lf\n", ans1, ans2);
flush();
return 0;
}
T3 Quoit Design
思路:
随机居然过不去……
我也是醉了
代码:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
typedef unsigned long long ull;
typedef unsigned int uint;
#define pb push_back
#define mp make_pair
namespace IO {
char buf_[1 << 21], *p1_ = buf_, *p2_ = buf_;
#define ch() \
(p1_ == p2_ && \
(p2_ = (p1_ = buf_) + fread(buf_, 1, 1 << 21, stdin), p1_ == p2_) \
? EOF \
: *p1_++)
inline int in() {
int s = 0, f = 1;
char x = getchar();
for (; x < '0' || x > '9'; x = getchar())
if (x == '-') f = -1;
for (; x >= '0' && x <= '9'; x = getchar()) s = (s * 10) + (x & 15);
return f == 1 ? s : -s;
}
char _buf[1 << 21];
int _p1 = -1;
inline void flush() {
fwrite(_buf, 1, _p1 + 1, stdout);
_p1 = -1;
}
inline void pc(char x) {
if (_p1 == (1 << 21) - 1) flush();
_buf[++_p1] = x;
}
inline void out(int x) {
char k[30];
int pos = 0;
if (!x) {
pc('0');
return;
}
if (x < 0) {
pc('-');
x = -x;
}
while (x) {
k[++pos] = (x % 10) | 48;
x /= 10;
}
for (int i = pos; i; i--) pc(k[i]);
return;
}
inline void out(string x) {
int len = x.size();
for (int i = 0; i < len; i++) pc(x[i]);
}
} // namespace IO
using namespace IO;
const int A = 2e5 + 5;
const double INF = 1e15;
const double EPS = 1e-7;
const double pi = acos(-1);
inline int cp(double u, double v) {
if (fabs(u - v) < EPS) return 0;
return u > v ? 1 : -1;
}
int n;
struct Point {
double x, y;
Point(double u = 0, double v = 0) { x = u, y = v; }
inline friend Point operator+(Point u, Point v) {
return Point(u.x + v.x, u.y + v.y);
}
inline friend Point operator-(Point u, Point v) {
return Point(u.x - v.x, u.y - v.y);
}
inline friend Point operator*(Point u, double v) {
return Point(u.x * v, u.y * v);
}
inline friend Point operator/(Point u, double v) {
return Point(u.x / v, u.y / v);
}
inline friend double operator^(Point u, Point v) {
return u.x * v.y - u.y * v.x;
}
inline friend double operator&(Point u, Point v) {
return u.x * v.x + u.y * v.y;
}
inline friend bool operator==(Point u, Point v) {
return !cp(u.x, v.x) && !cp(u.y, v.y);
}
inline friend bool operator!=(Point u, Point v) { return !(u == v); }
} p[A], pp[A];
int tot;
inline double dis(Point u, Point v) {
return sqrt((u.x - v.x) * (u.x - v.x) + (u.y - v.y) * (u.y - v.y));
}
inline bool cmp1(Point u, Point v) {
if (cp(u.x, v.x)) return u.x < v.x;
return u.y < v.y;
}
inline bool cmp2(Point u, Point v) {
if (cp(u.y, v.y)) return u.y < v.y;
return u.x < v.x;
}
double ans;
inline void work(int l, int r) {
if (l == r) return;
if (l + 1 == r) {
ans = min(ans, dis(p[l], p[r]));
return;
}
int mid = (l + r) >> 1;
work(l, mid - 1), work(mid + 1, r);
tot = 0;
for (int i = mid; i >= l && cp(p[mid].x - p[i].x, ans) == -1; i--)
pp[++tot] = p[i];
for (int i = mid + 1; i <= r && cp(p[i].x - p[mid].x, ans) == -1; i++)
pp[++tot] = p[i];
sort(pp + 1, pp + 1 + tot, cmp2);
for (int i = 1; i <= tot; i++)
for (int j = i + 1; j <= tot && cp(pp[j].y - pp[i].y, ans) == -1; j++)
ans = min(ans, dis(pp[i], pp[j]));
return;
}
signed main() {
n = in();
while (n) {
ans = INF;
for (int i = 1; i <= n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
sort(p + 1, p + 1 + n, cmp1);
work(1, n);
printf("%0.2lf\n", ans / 2);
n = in();
}
flush();
return 0;
}