【CDQ】 BZOJ 2716 天使玩偶
题意:先给出n个点, 然后有m个操作, (1, x, y) 表示查询离(x, y)最近点的曼哈顿距离, (2, x, y) 表示插入点 (x, y).
思路:. 距离点(x, y)最近的点和x的方位有四种, 左下左上右下右上, 然后只考虑一个方位, 另外的改变坐标即可. dis({x, y}, {x', y'}) = |x-x'| + |y-y'|. 在只考虑(x', y')在(x, y)的左下方时, 可以去掉绝对值 : dis = x+y - (x'+y'), 使x'+y'最大即可
代码:
#include <cstdio> #include <algorithm> using namespace std; const int maxn = 1000000 + 10; const int INF = 1000000000; int max_x; int ans[maxn]; struct BIT { int c[maxn]; int lowbit(int x) { return x & (-x); } void modify(int x, int d) { while(x <= max_x) { c[x] = max(c[x], d); x += lowbit(x); } } int query(int x) { int ret = 0; while(x > 0) { ret = max(ret, c[x]); x -= lowbit(x); } return ret; } void clear(int x) { while(x <= max_x) { c[x] = 0; x += lowbit(x); } } } bit; struct Node { int x, y, k, id; bool operator < (const Node& rhs) const { if(x != rhs.x) return x < rhs.x; return id < rhs.id; } } A[maxn]; #define a A[i] #define b A[j] struct CDQ { int n; Node T[maxn]; void init(int n) { this->n = n; sort(A+1, A+n+1); } void solve(int L, int R) { if(L >= R) return; int M = (L+R) >> 1; int i, j, p = L, q = M+1; for(i = L; i <= R; i++) if(a.id <= M) T[p++] = a; else T[q++] = a; for(i = L; i <= R; i++) A[i] = T[i]; solve(L, M); i = M+1; j = L; for(; i <= R; i++) if(a.k == 2) { for(; j <= M && b.x <= a.x; j++) if(b.k == 1) bit.modify(b.y, b.x+b.y); int t = bit.query(a.y); if(t) ans[a.id] = min(ans[a.id], a.x+a.y-t); } for(i = L; i < j; i++) if(a.k == 1) bit.clear(a.y); // 也可以开vis[]来区别清空 solve(M+1, R); merge(A+L, A+M+1, A+M+1, A+R+1, T+L); for(i = L; i <= R; i++) A[i] = T[i]; } } cdq; int main() { int n, m; scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%d %d", &a.x, &a.y); a.x++; a.y++; a.id = i; a.k = 1; max_x = max(max_x, max(a.x, a.y)); } for(int i = n+1; i <= n+m; i++) { scanf("%d %d %d", &a.k, &a.x, &a.y); a.x++; a.y++; a.id = i; max_x = max(max_x, max(a.x, a.y)); } max_x++; n += m; for(int i = 1; i <= n; i++) ans[i] = INF; cdq.init(n); cdq.solve(1, n); for(int i = 1; i <= n; i++) a.x = max_x - a.x; cdq.init(n); cdq.solve(1, n); for(int i = 1; i <= n; i++) a.y = max_x - a.y; cdq.init(n); cdq.solve(1, n); for(int i = 1; i <= n; i++) a.x = max_x - a.x; cdq.init(n); cdq.solve(1, n); for(int i = 1; i <= n; i++) if(ans[i] != INF) printf("%d\n", ans[i]); return 0; }