试题描述
输入
见题目,注意本题不能用文件输入输出
输出
见题目,注意本题不能用文件输入输出
输入示例
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[i][k] + (j - k)2 | 1 ≤ k ≤ j },显然可以用斜率优化来搞。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> #include <cstring> #include <string> #include <map> #include <set> using namespace std; const int BufferSize = 1 << 16; char buffer[BufferSize], *Head, *Tail; inline char Getchar() { if(Head == Tail) { int l = fread(buffer, 1, BufferSize, stdin); Tail = (Head = buffer) + l; } return *Head++; } 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 2147483647 int n, d[maxn][maxn], f[maxn][maxn]; char Map[maxn][maxn]; int sqr(int x) { return x * x; } struct Node { int x, y; Node() {} Node(int _, int __): x(_), y(__) {} } q[maxn]; double slop(Node a, Node b) { return ((double)a.y - b.y) / ((double)a.x - b.x); } int main() { n = read(); for(int i = 1; i <= n; i++) scanf("%s", Map[i] + 1); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) d[i][j] = oo; for(int j = 1; j <= n; j++) { int tmp = -1; for(int i = 1; i <= n; i++) { if(Map[i][j] == ‘1‘) tmp = i; if(tmp > 0) d[i][j] = min(d[i][j], sqr(i - tmp)); } tmp = -1; for(int i = n; i; i--) { if(Map[i][j] == ‘1‘) tmp = i; if(tmp > 0) d[i][j] = min(d[i][j], sqr(i - tmp)); } } for(int i = 1; i <= n; i++) { int ql = 1, qr = 0; for(int j = 1; j <= n; j++) { if(d[i][j] < oo) { Node t(j, d[i][j] + sqr(j)); while(ql < qr && slop(q[qr-1], q[qr]) > slop(q[qr], t)) qr--; q[++qr] = t; } while(ql < qr && slop(q[ql], q[ql+1]) < 2.0 * j) ql++; if(ql <= qr) f[i][j] = q[ql].y - 2 * j * q[ql].x + sqr(j); // printf("%d %d: %d\n", i, j, f[i][j]); } ql = 1; qr = 0; for(int j = n; j; j--) { if(d[i][j] < oo) { Node t(j, d[i][j] + sqr(j)); while(ql < qr && slop(q[qr-1], q[qr]) < slop(q[qr], t)) qr--; q[++qr] = t; } while(ql < qr && slop(q[ql], q[ql+1]) > 2.0 * j) ql++; if(ql <= qr) f[i][j] = min(f[i][j] ? f[i][j] : oo, q[ql].y - 2 * j * q[ql].x + sqr(j)); } } int q = read(); while(q--) { int a = read(), b = read(); printf("%d\n", f[a][b]); } return 0; }
时间: 2024-10-06 00:50:23