【单调队列】COGS 308. [HAOI2007] 理想的正方形

来源:互联网 发布:网络动漫制作公司 编辑:程序博客网 时间:2024/06/05 19:00

orz大神,附上链接:http://blog.csdn.net/orpinex/article/details/7179078

题目链接:http://cojs.tk/cogs/problem/problem.php?pid=308

分析:

对每一列用单调队列维护从这个点开始接下来n个数里面最大的和最小的

那么对于一列上的n个数,我们把它压成了一个数

lmax[i][j],lmin[i][j]分别表示以这个点为起点往下n个数里面最大和最小

那么我们对这个两个数组横向的也用单调队列维护

那么对于每一行,我们又把它压成了一个数

hmax[i][j],hmin[i][j]就表示这个点为左上角的正方形里面最大和最小的了

然后暴力O(ab)的找答案就可以了

代码:
#include<cstdio>#include<iostream>#include<queue>  using namespace std; int lmax[1008][1008],lmin[1008][1008],    hmax[1008][1008],hmin[1008][1008],      n,m,r,c,map[1008][1008],ans=2000000000;   typedef pair<int,int> pii;  deque<pii> qmax,qmin;  void calc(int col){qmax.clear();qmin.clear();for (int i=1;i<=r;i++){while (!qmax.empty()&&i-qmax.front().second>=n) qmax.pop_front();while (!qmin.empty()&&i-qmin.front().second>=n) qmin.pop_front();while (!qmax.empty()&&qmax.back().first<=map[i][col]) qmax.pop_back();while (!qmin.empty()&&qmin.back().first>=map[i][col]) qmin.pop_back();qmax.push_back(pii(map[i][col],i));qmin.push_back(pii(map[i][col],i));if (i>=n) lmax[i-n+1][col]=qmax.front().first, lmin[i-n+1][col]=qmin.front().first;}}void calc2(int col){qmax.clear();qmin.clear();for (int i=1;i<=c;i++){while (!qmax.empty()&&i-qmax.front().second>=n) qmax.pop_front();while (!qmin.empty()&&i-qmin.front().second>=n) qmin.pop_front();while (!qmax.empty()&&qmax.back().first<=lmax[col][i]) qmax.pop_back();while (!qmin.empty()&&qmin.back().first>=lmin[col][i]) qmin.pop_back();qmax.push_back(pii(lmax[col][i],i));qmin.push_back(pii(lmin[col][i],i));if (i>=n) hmax[col][i-n+1]=qmax.front().first, hmin[col][i-n+1]=qmin.front().first;}}int main(){freopen("square.in","r",stdin);freopen("square.out","w",stdout);cin>>r>>c>>n;for(int i=1;i<=r;i++)for (int j=1;j<=c;j++)cin>>map[i][j];    for (int i=1;i<=c;i++)  calc(i);    for (int j=1;j<=r;j++)  calc2(j);for (int i=1;i<=r-n+1;i++) for (int j=1;j<=c-n+1;j++)  ans=min(ans,hmax[i][j]-hmin[i][j]);    cout<<ans<<endl;return 0;}


原创粉丝点击