码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1047: [HAOI2007]理想的正方形

时间:2019-01-21 13:54:10      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:***   scanf   mat   res   --   while   div   处理   单调队列   

 可以叫做 二维的单调队列???

 

 

/**************************************************************
    Problem: 1047
    User: lxy8584099
    Language: C++
    Result: Accepted
    Time:2696 ms
    Memory:13776 kb
****************************************************************/
 
/*
    可以有 n^2的算法 
    先处理竖排的单调队列 然后往右推
    往下走一格 继续往右推
    用结构体搞得好模糊啊啊啊  
    每个数最大不超过 1e9  初始化小了 WA了好久 
*/
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e3+50;
struct pp
{
    int q[N],l,r;
    pp()
    {
        l=1;r=0;
        memset(q,0,sizeof(q));
    }
}mx[N],mn[N];
int n,m,r,ans=0x7fffffff;
int a[N][N],amx[N],amn[N],mxq[N],mxl,mxr,mnq[N],mnl,mnr;
int min(int a,int b) {return a>b?b:a;} 
void Work()
{
    mxl=mnl=1;mxr=mnr=0;
    for(int i=1;i<=m;i++)
    {
        amx[i]=a[mx[i].q[mx[i].l]][i];
        amn[i]=a[mn[i].q[mn[i].l]][i];
//      printf("i:%d \n",i);
//      printf("max:%d min:%d \n",amx[i],amn[i]);
    }
    for(int i=1;i<=m;i++)
    {
        while(mxl<=mxr&&mxq[mxl]<=i-r) mxl++;
        int mxnow=amx[i];
        while(mxl<=mxr&&amx[mxq[mxr]]<=mxnow) mxr--;
        mxq[++mxr]=i;
        while(mnl<=mnr&&mnq[mnl]<=i-r) mnl++;
        int mnnow=amn[i];
        while(mnl<=mnr&&amn[mnq[mnr]]>=mnnow) mnr--;
        mnq[++mnr]=i;
        if(i>=r)
        {
            ans=min(ans,amx[mxq[mxl]]-amn[mnq[mnl]]);
//          printf("    i:%d\n",i);
//          printf("    max:%d min:%d \n",amx[mxq[mxl]],amn[mnq[mnl]]);
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&r);  //  r*r MAt
    for(int i=1;i<=n;i++) 
        for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
    for(int i=1;i<=n;i++)    
    {
        for(int j=1;j<=m;j++)
        {
            while(mx[j].l<=mx[j].r&&mx[j].q[mx[j].l]<=i-r) mx[j].l++;
            while(mx[j].l<=mx[j].r&&a[mx[j].q[mx[j].r]][j]<=a[i][j]) mx[j].r--;
            mx[j].q[++mx[j].r]=i;
            while(mn[j].l<=mn[j].r&&mn[j].q[mn[j].l]<=i-r) mn[j].l++;
            while(mn[j].l<=mn[j].r&&a[mn[j].q[mn[j].r]][j]>=a[i][j]) mn[j].r--;
            mn[j].q[++mn[j].r]=i;
        }
        if(i>=r) Work();
    }
    printf("%d\n",ans);
    return 0;
}

 

bzoj 1047: [HAOI2007]理想的正方形

标签:***   scanf   mat   res   --   while   div   处理   单调队列   

原文地址:https://www.cnblogs.com/lxy8584099/p/10298019.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!