首页 > 代码库 > [BZOJ 1047][HAOI 2007]理想的正方形(二维滑动窗口+单调队列)
[BZOJ 1047][HAOI 2007]理想的正方形(二维滑动窗口+单调队列)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1047
思路:裸的二维上的滑动窗口问题,可以借鉴一维滑动窗口的思路。首先预处理出每一列j的、以第i行元素为结尾、长度为n的区间的最大值maxv[i][j]、最小值minv[i][j],然后再搞每一行,求出以每一行i结尾、行标上长度为n的区间、以第j列结尾、列标上长度为n的区间得到的二维区间最大值与最小值之差,遍历每一行得到这个差的最小值即为答案。
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <stdlib.h> #define MAXN 1200 #define INF 0x3f3f3f3f using namespace std; struct node { int val; //这个元素的值 int pos; //这个元素的下标 }q1[MAXN],q2[MAXN]; //q1维护一个单调递减队列,q2维护一个单调递增对了队列 int map[MAXN][MAXN]; int maxv[MAXN][MAXN],minv[MAXN][MAXN]; int pa,pb,n; //pa*pb大小的矩阵,从中取n*n大小的子矩阵 void init() { scanf("%d%d%d",&pa,&pb,&n); for(int i=1;i<=pa;i++) for(int j=1;j<=pb;j++) scanf("%d",&map[i][j]); } void work1() //第一次操作维护每一列的最值,最终得到第j列以第i个元素结尾的长度为n的区间的最大值、最小值 { int h1,t1,h2,t2; //队尾与队首的指针 for(int j=1;j<=pb;j++) //枚举列号j { h1=h2=t1=t2=0; for(int i=1;i<=pa;i++) //枚举长度为n的区间的最后一个元素下标i,当前长度为n的区间为[i-n+1,i { //维护队列q1 while(h1<t1&&q1[h1+1].pos<=i-n) //把队首不属于当前区间的都弹掉 h1++; while(h1<t1&&q1[t1].val<=map[i][j]) //把队尾不满足单调性的都弹掉 t1--; q1[++t1].val=map[i][j]; q1[t1].pos=i; //维护队列q2 while(h2<t2&&q2[h2+1].pos<=i-n) //把队首不属于当前区间的都弹掉 h2++; while(h2<t2&&q2[t2].val>=map[i][j]) //把队尾不满足单调性的都弹掉 t2--; q2[++t2].val=map[i][j]; q2[t2].pos=i; if(i<n) //区间里元素个数不够 { maxv[i][j]=INF; minv[i][j]=-INF; } else { maxv[i][j]=q1[h1+1].val; minv[i][j]=q2[h2+1].val; } } } } void work2() //第二次操作在第一次的基础上,遍历每一行,找出每一行i结尾的、以第j列结尾的长度为n的区间的最大值中的最小值、最小值中的最大值 { int ans=INF; int h1,t1,h2,t2; //队尾与队首的指针 for(int i=1;i<=pa;i++) //枚举行号i { h1=h2=t1=t2=0; for(int j=1;j<=pb;j++) //枚举长度为n的区间的最后一个元素下标j,当前长度为n的区间为[i-n+1,i { //维护队列q1 while(h1<t1&&q1[h1+1].pos<=j-n) //把队首不属于当前区间的都弹掉 h1++; while(h1<t1&&q1[t1].val<=maxv[i][j]) //把队尾不满足单调性的都弹掉 t1--; q1[++t1].val=maxv[i][j]; q1[t1].pos=j; //维护队列q2 while(h2<t2&&q2[h2+1].pos<=j-n) //把队首不属于当前区间的都弹掉 h2++; while(h2<t2&&q2[t2].val>=minv[i][j]) //把队尾不满足单调性的都弹掉 t2--; q2[++t2].val=minv[i][j]; q2[t2].pos=j; if(i>=n&&j>=n) ans=min(ans,q1[h1+1].val-q2[h2+1].val); } } printf("%d\n",ans); } int main() { init(); work1(); work2(); return 0; }
[BZOJ 1047][HAOI 2007]理想的正方形(二维滑动窗口+单调队列)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。