zoukankan      html  css  js  c++  java
  • [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[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;
    }
    
  • 相关阅读:
    MariaDB日志文件、备份与恢复
    实例讲解ip地址、子网掩码、可用地址范围的计算
    Nginx配置文件、优化详解
    Centos系统的升级
    编译安装nginx
    虚拟化云计算的相关概念汇总
    ELK日志管理
    Kubernetes 监控
    用 ConfigMap 管理配置
    K8s管理机密信息
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5827155.html
Copyright © 2011-2022 走看看