[COJ0988]WZJ的数据结构(负十二)

Posted xjr_01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[COJ0988]WZJ的数据结构(负十二)相关的知识,希望对你有一定的参考价值。

[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[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;
}

 

以上是关于[COJ0988]WZJ的数据结构(负十二)的主要内容,如果未能解决你的问题,请参考以下文章

[COJ0989]WZJ的数据结构(负十一)

[COJ0528]BJOI幸运数

COJ 1686:记忆化搜索

[COJ0574NOIP200406合并果子]

COJ 1697:模拟

[COJ6024]合并果子·改(强化版)