按时间分治,把每个询问拆成四个方向的查询,这样曼哈顿距离可以直接用减法得到
一维时间分治,二维x坐标排序,三维y坐标树状数组
#include
#include
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);
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;
}