傳送門: http://www.lydsy.com/JudgeOnline/problem.php?id=3663
題意: 兔子們決定在自己的城堡裏安排一些士兵進行防守。 給出
題解: 兩個兔子連線不於圓交等價於兩隻兔子的的極角序區間有交但不包含。腦補一下:兩個極角序區間如果剛好在邊緣相交就是剛好兩點連線和圓相切,相交多一點就相離,相交少一點就相交; 兩個極角序區間如果是包含關係並且一個邊緣相同兩點連線延長線和圓相切,內部區間移進去連線延長線和圓相交,內部區間往外移連線延長線和圓相離。
因爲我們只要判定兩極角序區間是交或者相離或包含,那麼我們對一個區間端點移動
#include<bits/stdc++.h>
const int N = 2333;
const double Pi = acos(-1);
struct rec{double l, r;} p[N];
int n, _n, R, x, y, cnt, ans;
double d, c, deg, a[N], h[N];
bool cmp(const rec &a, const rec &b) {return a.l < b.l;}
int LIS() {
if (!_n) return 0;
h[cnt = 1] = a[1];
for (int i = 2; i <= _n; i++) {
if (a[i] > h[cnt]) {h[++cnt] = a[i]; continue;};
int l = 1, r = cnt;
while (l < r) {
int mid = (l + r) >> 1;
if (h[mid] < a[i])
l = mid + 1;
else
r = mid;
}
h[l] = a[i];
}
return cnt;
}
int main() {
scanf("%d%d", &n, &R);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &x, &y);
d = sqrt(x * x + y * y);
deg = atan2(y , x);
c = acos(R / d);
p[i].l = deg - c;
p[i].r = deg + c;
while (p[i].l < -Pi) p[i].l += Pi * 2;
while (p[i].r > Pi) p[i].r -= Pi * 2;
if (p[i].l > p[i].r) std::swap(p[i].l, p[i].r);
}
std::sort(p + 1, p + n + 1, cmp);
for (int i = 1; i <= n; i++) {
_n = 0;
for (int j = i + 1; j <= n; j++)
if (p[j].l < p[i].r && p[j].r > p[i].r)
a[++_n] = p[j].r;
ans = std::max(ans, LIS() + 1);
}
printf("%d\n", ans);
return 0;
}