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

这种在矩形里面找矩形有固定的套路,不是容斥就是左右上下延伸,这个题就是向左向右延伸、、

然后手玩优化发现邻位转移比暴力要好一些,可以用splay统计,但复杂度不对

然后由于每一行互不影响于是可以单行同步操作

然后统计的时候就枚举列操作一遍

于是有限制最大值和最小值就转化为单调队列

所以这个题就是二维单调队列了


码:

#include<iostream>
#include<cstdio>
using namespace std;
#define N 1005
int a,b,n,i,j,v[N][N],z1[N],z2[N],z3[N],z4[N],q1[N][N],q3[N][N],qq1[N],qq3[N],zz1,zz2,zz3,zz4,ans=2000000009;
int main()
{
	scanf("%d%d%d",&a,&b,&n);
	for(i=1;i<=a;i++)
	for(j=1;j<=b;j++)
	scanf("%d",&v[i][j]);
	for(i=1;i<=b;i++)z1[i]=z3[i]=1,z2[i]=z4[i]=0;
	for(i=1;i<=a;i++)
	{
		for(j=1;j<=b;j++)
		{
			while(z1[j]<=z2[j]&&q1[j][z1[j]]<=i-n)++z1[j];
		while(z1[j]<=z2[j]&&v[q1[j][z2[j]]][j]<v[i][j])--z2[j];
			q1[j][++z2[j]]=i;
			while(z3[j]<=z4[j]&&q3[j][z3[j]]<=i-n)++z3[j];
		while(z3[j]<=z4[j]&&v[q3[j][z4[j]]][j]>v[i][j])--z4[j];
			q3[j][++z4[j]]=i;	
		}
		if(i>=n)
		{
			zz1=1;zz2=0;zz3=1;zz4=0;
			for(j=1;j<=b;j++)
			{
		while(zz1<=zz2&&qq1[zz1]<=j-n)++zz1;
		while(zz1<=zz2&&v[ q1[qq1[zz2]][z1[qq1[zz2]]] ][qq1[zz2]]<v[q1[j][z1[j] ]][j])--zz2;
			qq1[++zz2]=j;
		while(zz3<=zz4&&qq3[zz3]<=j-n)++zz3;
		while(zz3<=zz4&&v[ q3[qq3[zz4]][z3[qq3[zz4]]] ][qq3[zz4]]>v[q3[j][z3[j] ]][j])--zz4;
			qq3[++zz4]=j;
	if(j>=n)
	{	ans=min(ans,v[q1[qq1[zz1]][z1[qq1[zz1]]]][ qq1[zz1] ] -v[q3[qq3[zz3]][z3[qq3[zz3]]]][ qq3[zz3] ]);	
	}	
		    }
		}
	}
	printf("%d",ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值