bzoj1047

二维单调队列

rmq很明显会超时,如果这个序列是一维的,很明显就是个单调队列,现在就是把一维的单调队列转换为二维单调队列。

先求出每一列的窗口极值,然后对于每一行做单调队列,值就是之前求出每个位置结尾的极值,这样就求出了每个正方形的极值。

写起来要注意一些。

#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int a, b, n, ans = 1 << 30;
int d[N][N], mx[N][N], mn[N][N], q1[N], q2[N], mxx[N][N], mnn[N][N];
int main()
{
//  freopen("square.in", "r", stdin);
//  freopen("square.out", "w", stdout);
    scanf("%d%d%d", &a, &b, &n);
    for(int i = 1; i <= a; ++i)
        for(int j = 1; j <= b; ++j) scanf("%d", &d[i][j]);
    for(int i = 1; i <= a; ++i)
    {
        int l1 = 1, r1 = 0, l2 = 1, r2 = 0;
        for(int j = 1; j <= b; ++j)
        {
            while(l1 <= r1 && j - q1[l1] + 1 > n) ++l1;
            while(l1 <= r1 && d[i][j] > d[i][q1[r1]]) --r1;
            while(l2 <= r2 && j - q2[l2] + 1 > n) ++l2;
            while(l2 <= r2 && d[i][j] < d[i][q2[r2]]) --r2;
            q1[++r1] = j;
            q2[++r2] = j;
            mx[i][j] = d[i][q1[l1]];
            mn[i][j] = d[i][q2[l2]];
//          printf("mx[%d][%d]=%d mn[%d][%d]=%d\n", i, j, mx[i][j], i, j, mn[i][j]);
        }
    }
    for(int j = n; j <= b; ++j)
    {
        int l1 = 1, r1 = 0, l2 = 1, r2 = 0;
        for(int i = 1; i <= a; ++i)
        {
            while(l1 <= r1 && i - q1[l1] + 1 > n) ++l1;
            while(l1 <= r1 && mx[i][j] > mx[q1[r1]][j]) --r1;
            while(l2 <= r2 && i - q2[l2] + 1 > n) ++l2;
            while(l2 <= r2 && mn[i][j] < mn[q2[r2]][j]) --r2;
            q1[++r1] = i;
            q2[++r2] = i;
            mxx[i][j] = mx[q1[l1]][j];
            mnn[i][j] = mn[q2[l2]][j];
//          printf("mxx[%d][%d]=%d mnn[%d][%d]=%d\n", i, j, mxx[i][j], i, j, mnn[i][j]);
        }
    }
    for(int i = n; i <= a; ++i)
        for(int j = n; j <= b; ++j) ans = min(ans, mxx[i][j] - mnn[i][j]);
    printf("%d\n", ans);
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

时间: 2024-11-05 12:15:18

bzoj1047的相关文章

[BZOJ1047][HAOI2007]理想的正方形

1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3481  Solved: 1917 [Submit][Status][Discuss] Description 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值 的差最小. Input 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数.每 行相邻

bzoj1047题解

[解题思路] (p.s.:刚看的时候一脸懵逼..没看见N已经给定了,还以为要用某些高明的方法..果然还是太naive了..) 两遍预处理,第一遍处理出f[i][j][0/1]表示第i行从j-n+1~j中的最小/大值,第二遍基于f数组处理出g[i][j][0/1]表示以(i,j)为右下角的长度为n的正方形中最小/大值,然后O(ab)枚举即可. 预处理可以用单调队列均摊O(1),然而本人比较懒..直接上了STL set,均摊复杂度O(log2n). 总复杂度O(ab)(单调队列)或O(ablog2n

[BZOJ1047] [HAOI2007] 理想的正方形 (单调队列)

Description 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. Input 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数.每行相邻两数之间用一空格分隔.100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100 Output 仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值. Sample In

【bzoj1047】[HAOI2007]理想的正方形 二维RMQ

题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数.每行相邻两数之间用一空格分隔.100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000 输出 仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值. 样例输入 5 4 2 1 2 5 6 0 1

【单调队列】bzoj1047 [HAOI2007]理想的正方形

先把整个矩阵处理成b[n][m-K+1].c[n][m-K+1]大小的两个矩阵,分别存储每行每K个数中的最大.最小值,然后再通过b.c处理出d.e分别表示K*K大小的子矩阵中的最大.最小值即可.单调队列暴力. #include<cstdio> #include<algorithm> using namespace std; #define N 1001 int n,m,K,a[N][N],b[N][N],c[N][N],q[N],head,tail,d[N][N],e[N][N];

bzoj1047理想的正方形

题目链接 纪念又双叒叕的一道暴力碾标算的题 我们考虑纯暴力 #include<iostream> #include<cstdio> #include<algorithm> using namespace std; int a,b,n; int map[1010][1010]; int ans=0x3f3f3f3f; int main() { scanf("%d%d%d",&a,&b,&n); for(int i=1;i<

20160522~20160528

20160523 bzoj2561 http://www.lydsy.com/JudgeOnline/problem.php?id=2561 题意:给定一个连通无向图,假设现在加入一条边权为L的边(u,v),求需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上.N≤20000,M≤200000 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4

大神刷题表

9月27日 后缀数组:[wikioi3160]最长公共子串 dp:NOIP2001统计单词个数 后缀自动机:[spoj1812]Longest Common Substring II [wikioi3160]最长公共子串 [spoj7258]Lexicographical Substring Search 扫描线+set:[poj2932]Coneology 扫描线+set+树上删边游戏:[FJOI2013]圆形游戏 结论:[bzoj3706][FJ2014集训]反色刷 最小环:[poj1734

[转载]hzwer的bzoj题单

counter: 664BZOJ1601 BZOJ1003 BZOJ1002 BZOJ1192 BZOJ1303 BZOJ1270 BZOJ3039 BZOJ1191 BZOJ1059 BZOJ1202 BZOJ1051 BZOJ1001 BZOJ1588 BZOJ1208 BZOJ1491 BZOJ1084 BZOJ1295 BZOJ3109 BZOJ1085 BZOJ1041 BZOJ1087 BZOJ3038 BZOJ1821 BZOJ1076 BZOJ2321 BZOJ1934 BZOJ