有删点,动态的询问一个点向左向右能看到的最远的点。
假设没有删点,这个显然可以直接单调栈前后扫两遍搞定。
如果有了删点,考虑cdq分治。
cdq分治搞不了删点,倒着变成加点。
第一维是时间,第二维是x
对于分治到区间(l,r),设m=l+r>>1
cdq分治让我们只用去处理[l..m]的插入对[m+1..r]的询问的影响。
强行建出单调栈,求能看到的最远的点由于不能把询问的点加入单调栈,所以要套上一个二分。
Code:
#include
#include
#include
#define db double
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const db pi = acos(-1);
const int N = 2e5 + 5;
int n, Q, x, del[N], tot, z[N];
struct node {
int x, y, i;
} a[N], b[N];
db ans[N][2];
int cmp(node a, node b) {return a.x < b.x;}
int cmp2(node a, node b) {return a.y < b.y;}
db ji(node a, node b) {return (db) (a.y - b.y) / (a.x - b.x);}
db jj(int x, int y) {return ji(a[x], a[y]);}
void in1(int x) {
while(z[0] > 1 && jj(z[z[0] - 1], z[z[0]]) < jj(z[z[0]], x))
z[0] --;
z[++ z[0]] = x;
}
void in2(int x) {
while(z[0] > 1 && jj(z[z[0] - 1], z[z[0]]) > jj(z[z[0]], x))
z[0] --;
z[++ z[0]] = x;
}
void cdq(int x, int y) {
if(x == y) return;
int m = x + y >> 1;
cdq(x, m); cdq(m + 1, y);
sort(b + x, b + m + 1, cmp2); sort(b + m + 1, b + y + 1, cmp2);
z[0] = 0; int l = x - 1;
fo(i, m + 1, y) if(b[i].i) {
while(l < m && b[l + 1].y < b[i].y)
if(!b[++ l].i) in1(b[l].y);
int as = z[0];
for(int l = 1, r = z[0] - 1; l <= r; ) {
int m = l + r >> 1;
if(ji(a[z[m]], a[b[i].y]) < ji(a[z[m + 1]], a[b[i].y]))
as = m, r = m - 1; else l = m + 1;
}
if(as) ans[b[i].i][0] = min(ans[b[i].i][0], pi / 2 + atan(ji(a[z[as]], a[b[i].y])));
}
z[0] = 0; l = m + 1;
fd(i, y, m + 1) if(b[i].i) {
while(l > x && b[l - 1].y > b[i].y)
if(!b[-- l].i) in2(b[l].y);
int as = z[0];
for(int l = 1, r = z[0] - 1; l <= r; ) {
int m = l + r >> 1;
if(jj(z[m], z[m + 1]) > ji(a[z[m + 1]], a[b[i].y]))
as = m, r = m - 1; else l = m + 1;
}
if(as) ans[b[i].i][1] = min(ans[b[i].i][1], pi / 2 - atan(ji(a[z[as]], a[b[i].y])));
}
}
int main() {
freopen("a.in", "r", stdin);
scanf("%d %d", &n, &Q);
fo(i, 1, n) scanf("%d %d", &a[i].x, &a[i].y), a[i].i = i;
sort(a + 1, a + n + 1, cmp);
tot = Q;
fo(i, 1, Q) {
scanf("%d %d", &b[i].x, &b[i].y);
if(b[i].x == 0) del[b[i].y] = 1; else b[i].i = i;
ans[i][0] = ans[i][1] = 1e9;
}
fo(i, 1, n) if(!del[i]) b[++ tot].x = 0, b[tot].y = i;
fo(i, 1, tot / 2) swap(b[i], b[tot - i + 1]);
cdq(1, tot);
fo(i, 1, Q) if(ans[i][0] != 1e9)
printf("%.6lf\n", ans[i][0] + ans[i][1]);
}