题目链接(牛客重现赛)
题意:给定一段路程(线段,起点S,终点T),在其一侧
n
n
n个点,对其中任意两个点来说,在从S到T的过程中对二者进行观测,有可能会发生左右位置的互换(一开始
p
i
p_i
pi在
p
j
p_j
pj左侧,后来
p
i
p_i
pi在
p
j
p_j
pj右侧),现在给你
m
m
m个询问:对于点
h
i
h_i
hi,与其它点第
k
i
k_i
ki次发生观测位置互换时,其坐标如何,如果不存在,输出"-1"。(
1
≤
n
≤
1000
,
1
≤
m
≤
1
0
4
1\le n\le1000,1\le m\le10^4
1≤n≤1000,1≤m≤104)
思路:显然对于每一次询问来说,假定当前点所在位置为
H
H
H,询问点为
P
h
i
P_{h_i}
Phi,直线
H
P
h
i
HP_{h_i}
HPhi在
H
H
H移动的过程中扫过第
k
i
k_i
ki个点时,
H
H
H所在位置即为答案。当然,在这之前需要预处理,对每一个点
P
x
i
P_{x_i}
Pxi预处理它和其它所有点所在直线和
S
T
ST
ST的交点,按到
S
S
S的距离排序即可。复杂度大概是
O
(
n
2
l
o
g
(
n
)
)
O(n^2log(n))
O(n2log(n))
#include <bits/stdc++.h>
#define dsc(x) scanf("%d", &x)
#define rep(i, st, en) for (int i = st; i <= en; i++)
#define rrep(i, st, en) for (int i = st; i >= en; i--)
#define pb push_back
using namespace std;
const int N = 1E3 + 10;
const double eps = 1e-8;
double fabs(double x) {
if (x < 0) return -x;
return x;
}
int sgn(double x) {
if (fabs(x) < eps) return 0;
if (x < 0)
return -1;
else
return 1;
}
struct Point {
double x, y;
int ind;
Point() {}
Point(double _x, double _y) {
x = _x;
y = _y;
ind = 0;
}
void input() { scanf("%lf%lf", &x, &y); }
void output() {
if (sgn(x) == 0) x = 0;
if (sgn(y) == 0) y = 0;
printf("%.10f %.10f\n", x, y);
}
double operator^(const Point &B) { return x * B.y - y * B.x; }
Point operator-(const Point &B) const { return Point(x - B.x, y - B.y); }
};
Point Now;
Point S, T, node[N];
struct Line {
Point s, e;
Line() {}
Line(Point _s, Point _t) {
s = _s;
e = _t;
}
int relation(Point P) {
int c = sgn((P - s) ^ (e - s));
if (c < 0)
return 1;
else if (c < 0)
return 2;
else
return 3;
}
int linecross(Line v) {//当前直线与线段v是否有交点,有交点返回2
int d1 = sgn((e - s) ^ (v.s - s));
int d2 = sgn((e - s) ^ (v.e - s));
if ((d1 ^ d2) == -2) return 2;//有交点
return (d1 == 0 || d2 == 0);
}
Point crosspoint(Line v) {
double a1 = (v.e - v.s) ^ (s - v.s);
double a2 = (v.e - v.s) ^ (e - v.s);
return Point((s.x * a2 - e.x * a1) / (a2 - a1),
(s.y * a2 - e.y * a1) / (a2 - a1));
}
double Len() {
return sqrt((e.x - s.x) * (e.x - s.x) + (e.y - s.y) * (e.y - s.y));
}
};
bool cmp1(Point A, Point B) { return Line(S, A).Len() < Line(S, B).Len(); }
int main() {
int n, m;
dsc(n);
dsc(m);
vector<Point> v[n + 1];
S.input();
T.input();
for (int i = 1; i <= n; i++) {
node[i].input();
node[i].ind = i;
}
Line st(S, T);
rep(i, 1, n) {
rep(j, 1, n) {
if (i == j) continue;
Line L1(node[i], node[j]);
if (L1.linecross(st) != 2) continue;
Point c = L1.crosspoint(st);
v[i].push_back(c);
}
sort(v[i].begin(), v[i].end(), cmp1);
}
rep(i, 1, m) {
int h, k, cnt = -1, now = 0;
dsc(h);
dsc(k);
if (v[h].size() < k) {
printf("-1\n");
continue;
}
v[h][k - 1].output();
// node[cnt] node[now]
}
return 0;
}