[COJ0988]WZJ的数据结构(负十二)
试题描述
输入
见题目,注意本题不能用文件输入输出
输出
见题目,注意本题不能用文件输入输出
输入示例
4 1000 0001 0000 0000 4 1 1 1 2 1 3 1 4
输出示例
0 1 2 1
数据规模及约定
1≤N≤1500,M≤N×N 且 M≤300000。
题解
我们先预处理出 d[i][j] 表示距离 (i, j) 这个点最近的点(只考虑第 i 行)的欧几里得距离的平方。那么我们可以枚举行数 i,然后变成一维问题从上往下扫,设 f(i, j) 为离该点最近的点的欧几里得距离的平方(即答案),那么有 f(i, j) = min{ d[k][j] + (i - k)2 | 1 ≤ k ≤ i },显然可以用斜率优化来搞,最后记得再从下往上扫一遍。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cctype> #include <algorithm> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); } return x * f; } #define maxn 1510 #define oo 1000000000 struct Vec { int x, y; Vec() {} Vec(int _, int __): x(_), y(__) {} Vec operator - (const Vec& t) const { return Vec(x - t.x, y - t.y); } int operator ^ (const Vec& t) const { return x * t.y - y * t.x; } } ps[maxn]; bool Map[maxn][maxn]; int n, dis[maxn][maxn], f[maxn][maxn], g[maxn][maxn], q[maxn], hd, tl; bool isup(Vec a, int k) { return a.y <= a.x * k; } bool isup(Vec a, Vec b) { return (b ^ a) >= 0; } int main() { n = read(); for(int i = 1; i <= n; i++) { char c = getchar(); while(!isdigit(c)) c = getchar(); int j = 0; while(isdigit(c)) Map[i][++j] = c - '0', dis[i][j] = oo, c = getchar(); } for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) if(Map[i][j]) dis[i][j] = 0; else if(j > 1 && dis[i][j-1] < oo) dis[i][j] = min(dis[i][j], dis[i][j-1] + 1); for(int j = n; j; j--) if(Map[i][j]) dis[i][j] = 0; else if(j < n && dis[i][j+1] < oo) dis[i][j] = min(dis[i][j], dis[i][j+1] + 1); for(int j = 1; j <= n; j++) if(dis[i][j] < oo) dis[i][j] = dis[i][j] * dis[i][j]; // for(int j = 1; j <= n; j++) printf("%d%c", dis[i][j], j < n ? ' ' : ' '); } for(int j = 1; j <= n; j++) { hd = 1; tl = 0; for(int i = 1; i <= n; i++) { if(dis[i][j] < oo) { ps[i] = Vec(i, dis[i][j] + i * i); while(hd < tl && isup(ps[q[tl]] - ps[q[tl-1]], ps[i] - ps[q[tl-1]])) tl--; q[++tl] = i; } while(hd < tl && isup(ps[q[hd+1]] - ps[q[hd]], 2 * i)) hd++; // printf("%d: (%d, %d) ", hd, ps[q[hd]].x, ps[q[hd]].y); if(hd <= tl) f[i][j] = ps[q[hd]].y - 2 * i * ps[q[hd]].x + i * i; else f[i][j] = oo; // printf("%d %d: %d ", i, j, f[i][j]); } for(int i = 1; i <= (n >> 1); i++) swap(dis[i][j], dis[n-i+1][j]); hd = 1; tl = 0; for(int i = 1; i <= n; i++) { if(dis[i][j] < oo) { ps[i] = Vec(i, dis[i][j] + i * i); while(hd < tl && isup(ps[q[tl]] - ps[q[tl-1]], ps[i] - ps[q[tl-1]])) tl--; q[++tl] = i; } while(hd < tl && isup(ps[q[hd+1]] - ps[q[hd]], 2 * i)) hd++; if(hd <= tl) g[i][j] = ps[q[hd]].y - 2 * i * ps[q[hd]].x + i * i; else g[i][j] = oo; } for(int i = 1; i <= n; i++) f[i][j] = min(f[i][j], g[n-i+1][j]); } int q = read(); while(q--) { int x = read(), y = read(); printf("%d ", f[x][y]); } return 0; }