zoukankan      html  css  js  c++  java
  • 【单调队列】bzoj1047 [HAOI2007]理想的正方形

    先把整个矩阵处理成b[n][m-K+1]、c[n][m-K+1]大小的两个矩阵,分别存储每行每K个数中的最大、最小值,然后再通过b、c处理出d、e分别表示K*K大小的子矩阵中的最大、最小值即可。单调队列暴力。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 1001
    int n,m,K,a[N][N],b[N][N],c[N][N],q[N],head,tail,d[N][N],e[N][N];
    int ans=2147483647;
    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]);
    	for(int i=1;i<=n;++i)
    	  {
    	  	head=tail=q[1]=1;
    		for(int j=2;j<=K;++j)
    	  	  {
    	  	 	while(a[i][j]<=a[i][q[tail]] && tail>=head) --tail;
    	  		q[++tail]=j;
    	  	  }
    		b[i][1]=a[i][q[head]];
    		for(int j=K+1;j<=m;++j)
    	  	  {
    	  		if(q[head]<j-K+1) ++head;
    	  		while(a[i][j]<=a[i][q[tail]] && tail>=head) --tail;
    	  		q[++tail]=j;
    	  		b[i][j-K+1]=a[i][q[head]];
    	  	  }
    		head=tail=q[1]=1;
    		for(int j=2;j<=K;++j)
    	  	  {
    	  	 	while(a[i][j]>=a[i][q[tail]] && tail>=head) --tail;
    	  		q[++tail]=j;
    	  	  }
    		c[i][1]=a[i][q[head]];
    		for(int j=K+1;j<=m;++j)
    	  	  {
    	  		if(q[head]<j-K+1) ++head;
    	  		while(a[i][j]>=a[i][q[tail]] && tail>=head) --tail;
    	  		q[++tail]=j;
    	  		c[i][j-K+1]=a[i][q[head]];
    	  	  }
    	  }
    	for(int i=1;i<=m-K+1;++i)
    	  {
    	  	head=tail=q[1]=1;
    	  	for(int j=2;j<=K;++j)
    	  	  {
    	  	 	while(b[j][i]<=b[q[tail]][i] && tail>=head) --tail;
    	  		q[++tail]=j;
    	  	  }
    		d[1][i]=b[q[head]][i];
    		for(int j=K+1;j<=n;++j)
    	  	  {
    	  		if(q[head]<j-K+1) ++head;
    	  		while(b[j][i]<=b[q[tail]][i] && tail>=head) --tail;
    	  		q[++tail]=j;
    	  		d[j-K+1][i]=b[q[head]][i];
    	  	  }
    	  	head=tail=q[1]=1;
    	  	for(int j=2;j<=K;++j)
    	  	  {
    	  	 	while(c[j][i]>=c[q[tail]][i] && tail>=head) --tail;
    	  		q[++tail]=j;
    	  	  }
    		e[1][i]=c[q[head]][i];
    		for(int j=K+1;j<=n;++j)
    	  	  {
    	  		if(q[head]<j-K+1) ++head;
    	  		while(c[j][i]>=c[q[tail]][i] && tail>=head) --tail;
    	  		q[++tail]=j;
    	  		e[j-K+1][i]=c[q[head]][i];
    	  	  }
    	  }
    	for(int i=1;i<=n-K+1;++i)
    	  for(int j=1;j<=m-K+1;++j)
    	    ans=min(ans,e[i][j]-d[i][j]);
    	printf("%d
    ",ans);
    	return 0;
    }
  • 相关阅读:
    Unity PhysicsScene测试
    游戏编程精粹学习
    Unity StreamingMipmaps 简单测试
    稀疏贴图 SparseTexture
    前端工程师是怎样一种职业
    web资源预加载-生产环境实践
    2019年终总结——三十而立
    一种前端灰度发布方案
    2018年终总结——越过山丘
    记录一个前端bug的解决过程
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4319794.html
Copyright © 2011-2022 走看看