[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;
}
时间: 2024-10-06 00:50:23

[COJ0988]WZJ的数据结构(负十二)的相关文章

12. 蛤蟆的数据结构进阶十二排序实现之直接插入法

12. 蛤蟆的数据结构进阶十二排序实现之直接插入法 本篇名言:"路是脚踏出来的 ,历史是人写出来的,人的每一步行动都在书定自己的历史. --吉鸿昌" 接下来看下直接插入法的实现. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47687631 1.  直接插入法 直接插入排序(straightinsertion sort) 每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序. 第一趟比较前两

COJ 1010 WZJ的数据结构(十) 线段树区间操作

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

COJ 1010 WZJ的数据结构(十) 线段树的地狱

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

数据结构(十二)——排序算法

数据结构(十二)--排序算法 一.排序简介 1.排序的一般定义 排序是计算机中经常进行的操作,目的在于将一组无序的数据元素调整为有序的数据元素.序列:1,20,45,5,2,12排序后:1,2,5,12,20,45 2.排序的数学定义 3.排序的稳定性 如果序列中的两个元素R[i].R[j],关键字分别为K[i].K[j],并且在排序之前R[i]排在R[j]前面,如果排序操作后,元素R[i]仍然排在R[j]前面,则排序方法是稳定的:否则排序是不稳定的. 4.排序实现的关键 比较:任意两个数据元素

数据结构(十二)散列表

定义 以下简称hahs 应用场景 适合查找与给定值相同的数据,不适合做范围查找,1对多映射查找 问题 冲突,散列表的理论依据是每个不同的关键字通过散列算法得到的结果都是唯一的,而现实中有可能出现几个结果相同的关键字. hash算法 构造一个散列算法考虑几个方面 直接定址法 按如下公式计算出关键字的hash值,当原始的key不重复,则得到的hash值就不会冲突 数字分析法 抽取关键字的一部分作为hash值 例如手机号,一般可以取后4位或者后4位的变形作为hash值,(公司内部场景) 平方取中法 折

COJ968 WZJ的数据结构(负三十二)

WZJ的数据结构(负三十二) 难度级别:D: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有一盏灯,初始均亮着.请你设计一个数据结构,回答M次操作. 1 x:将节点x上的灯拉一次,即亮变灭,灭变亮. 2 x k:询问当前所有亮灯的节点中距离x第k小的距离(注意如果x亮着也算入). 输入 第一行为一个正整数N.第二行到第N行每行三个正整数ui,vi,wi.表示一条树边从ui到vi,距离为wi

COJ 0970 WZJ的数据结构(负三十)树分治

WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计一个数据结构,回答M次操作. 1 x v:对于树上的每一个节点y,如果将x.y在树上的距离记为d,那么将y节点的权值加上d*v. 2 x:询问节点x的权值. 输入 第一行为一个正整数N.第二行到第N行每行三个正整数ui,vi,wi.表示一条树边从ui到vi,距离为wi.第N+1行为一个正整数M.最后

COJ 0981 WZJ的数据结构(负十九)树综合

WZJ的数据结构(负十九) 难度级别:E: 运行时间限制:15000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 WZJ的数据结构中有很多都是关于树的.这让很多练习模板的同学还要找来找去很不爽,于是WZJ跟小伙伴们一块商量如何将这些题汇拢到一块去: WZJ:为了大家简单,我规定一开始是一棵有根树. LZJ:那我一定得加上换根操作喽. XJR:链信息修改,链信息增加,链信息翻倍,维护链信息的最大,最小,总和肯定很好做. CHX:子树信息修改,子树信息增加,子树

COJ 0979 WZJ的数据结构(负二十一)

WZJ的数据结构(负二十一) 难度级别:C: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你实现一个数据结构,完成这样的功能: 给你一个N个点的图,初始状态无边. 每次加入一条双向边(u,v,w),若加入后没有构成一棵生成树,输出“Not Yet”,否则输出当前最小生成树的权值. 输入 第一行两个正整数N,M.表示有N个点M个操作.接下来M行每行三个正整数u,v,w. 输出 每次加入一条双向边(u,v,w),若加入后没有构成一棵生成