BZOJ1047 - [HAOI2007]理想的正方形
题意简述
有一个由
分析
首先处理出
然后以
以上都可以通过单调队列实现。
总时间复杂度
实现
开两个单调队列,一个递增,一个递减。
代码
//[HAOI2007]理想的正方形
#include <cstdio>
#include <algorithm>
using namespace std;
int const N=1e3+10;
int const INF=0x7FFFFFFF;
int n,m,k,a[N][N];
int c[2][N][N];
struct queue
{
int op,cl,type;
struct ele{int x,y,val;} qu[N];
void clear() {op=1,cl=0;}
void push(int x,int y,int val)
{
if(type==0) while(qu[cl].val<=val && cl>=op) cl--;
else while(qu[cl].val>=val && cl>=op) cl--;
cl++; qu[cl].x=x,qu[cl].y=y,qu[cl].val=val;
}
int topX() {return qu[op].x;}
int topY() {return qu[op].y;}
int topV() {return qu[op].val;}
}q[2];
void push1(int x,int y) {q[0].push(x,y,a[x][y]); q[1].push(x,y,a[x][y]);}
void push2(int x,int y) {q[0].push(x,y,c[0][x][y]); q[1].push(x,y,c[1][x][y]);}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
q[0].type=0; q[1].type=1;
for(int i=1;i<=n;i++)
{
q[0].clear(); q[1].clear();
for(int j=1;j<=k;j++) push1(i,j);
c[0][i][1]=q[0].topV();
c[1][i][1]=q[1].topV();
for(int j=2;j<=m-k+1;j++)
{
if(q[0].topY()<j) q[0].op++;
if(q[1].topY()<j) q[1].op++;
push1(i,j+k-1);
c[0][i][j]=q[0].topV();
c[1][i][j]=q[1].topV();
}
}
int ans=INF;
for(int j=1;j<=m-k+1;j++)
{
q[0].clear(); q[1].clear();
for(int i=1;i<=k;i++) push2(i,j);
ans=min(ans,q[0].topV()-q[1].topV());
for(int i=2;i<=n-k+1;i++)
{
if(q[0].topX()<i) q[0].op++;
if(q[1].topX()<i) q[1].op++;
push2(i+k-1,j);
ans=min(ans,q[0].topV()-q[1].topV());
}
}
printf("%d",ans);
return 0;
}
注意
代码可能很难写的简洁…我尽力了