BZOJ 1047 [HAOI2007]理想的正方形
2015-08-13 14:37
423 查看
1047: [HAOI2007]理想的正方形
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2054 Solved: 1091
[Submit][Status][Discuss]
Description
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。Input
第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。Output
仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。Sample Input
5 4 21 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
Sample Output
1HINT
问题规模(1)矩阵中的所有数都不超过1,000,000,000
(2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10
(3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100
Source
题解:太神了,膜郑爷%%%首先看数据范围,很显然要求线性算法,那就是说只能扫一次喽,那就是说要O(1)维护喽,那就是说要敲单调队列喽。。。
既然要写moque,就要着重考虑一下啥时候该删除了。首先把窝萌的查询的框分成4部分:
假设窝萌的小正方形从左上角往下动,那么很显然1区域对于两个方向只是添加,2区域对于y方向是增加,对于x方向是维护,3区域对于x方向是增加,对于y方向是维护,4区域对于两个方向都是维护。
那就好办呀,对于不同的部分用不同的办法维护不就好了。。。。
注意这里有个细节:比如窝萌维护1区域的时候一定是1~n-1!!!为啥?因为i=n的时候就需要开始回答了!
然后说一下单调队列:窝萌还需要记录一下进队的时间,用来维护pop操作。然后就码就行了。。。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<stack> #include<queue> #include<cstring> #define PAU putchar(' ') #define ENT putchar('\n') using namespace std; const int maxn=1000+10,inf=-1u>>1; struct moque{ int a1[1001],t1[1001],a2[1001],t2[1001]; int st1,ed1,st2,ed2; moque(){st1=1;ed1=0;st2=1;ed2=0;} void pushmi(int x,int t){ while((st1<=ed1)&&(x<=a1[ed1]))ed1--;ed1++;a1[ed1]=x;t1[ed1]=t;return; } void pushmx(int x,int t){ while((st2<=ed2)&&(x>=a2[ed2]))ed2--;ed2++;a2[ed2]=x;t2[ed2]=t;return; } void pop(int t){ if(t1[st1]==t)st1++;if(t2[st2]==t)st2++;return; } int qmin(){return a1[st1];} int qmax(){return a2[st2];} }qx[maxn],qy[maxn]; int a,b,n,A[maxn][maxn]; inline int read(){ int x=0,sig=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=0; for(;isdigit(ch);ch=getchar())x=10*x+ch-'0'; return sig?x:-x; } inline void write(int x){ if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; } int main(){ a=read();b=read();n=read(); for(int i=1;i<=a;i++)for(int j=1;j<=b;j++)A[i][j]=read(); for(int i=1;i<n;i++){ for(int j=1;j<n;j++)qx[i].pushmi(A[i][j],j),qx[i].pushmx(A[i][j],j); for(int j=n;j<=b;j++){ qx[i].pushmi(A[i][j],j);qx[i].pushmx(A[i][j],j); qy[j].pushmi(qx[i].qmin(),i);qy[j].pushmx(qx[i].qmax(),i); qx[i].pop(j-n+1); } }int ans=inf; for(int i=n;i<=a;i++){ for(int j=1;j<n;j++)qx[i].pushmi(A[i][j],j),qx[i].pushmx(A[i][j],j); for(int j=n;j<=b;j++){ qx[i].pushmi(A[i][j],j);qx[i].pushmx(A[i][j],j); qy[j].pushmi(qx[i].qmin(),i);qy[j].pushmx(qx[i].qmax(),i); ans=min(ans,qy[j].qmax()-qy[j].qmin()); qx[i].pop(j-n+1);qy[j].pop(i-n+1); } }write(ans); return 0; }
相关文章推荐
- sql comm
- HDU ACM 2008 数值统计
- 数据库出现ORA-00283/ORA-01610的问题
- iOS中关于登录验证方面的问题的解决
- HDU 1004 Let the Balloon Rise (map使用)
- 详解EBS接口开发之库存事务处理-物料批次导入
- 修改mysql数据库root用户的密码
- Groovy 数据库应用开发实践-SQL对象托管和封装
- 设计模式:26 项目多也别傻做_享元模式
- 通过boost::bind实现c++多线程
- 获取公网IP
- Exceptions不能跨进程catch
- 64-bit Itanium与x64
- mac系统Sublime 2 乱码问题
- C++常用字符串分割方法实例汇总
- 修改fiddler中CustomRules.js的Request或Response
- USB枚举过程
- unable to instantiate activity...
- ArcGIS Server 10.1 错误 service failed to start,
- LVS + Keepalived 实现负载均衡