zoukankan      html  css  js  c++  java
  • P2216理想的正方形题解

    又是一道题解满了的题
    按照题意,我们需要维护一个 (n imes n) 大小的矩阵内的最大最小值。

    显然一个二维的东西不好直接维护。

    我们可以先维护行的最值,然后再用单调队列维护连续(n)行的最值。(如果暂时不理解这句话请先看下面的操作。)

    (mx[i][j],mn[i][j]) 分别表示 (a[i][j]) ~ (a[i][j+n-1]) 中的最大/最小值,用单调队列维护,一次维护一行,共维护 (n) 次,复杂度(O(n^2))

    然后按列维护,维护 (mx[i][j]) ~ (mx[i+n-1][j]) 的最大值以及 (mn[i][j]) ~ (mn[i+n-1][j]) 的最小值,作差取 (max)。这样就可以维护 (n imes n)的矩阵了。

    (Code)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<ctime>
    #include<deque>
    #define pa pair<int,int>
    #define rg register
    #define ls (k<<1)
    #define rs (k<<1|1)
    using namespace std;
    typedef long long ll;
    const double eps=1e-13;
    inline ll read(){
    	char ch=getchar();
        ll x=0;bool f=0;
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-') f=1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<3)+(x<<1)+(ch^48);
    		ch=getchar();
    	}
    	return f?-x:x;
    }
    int n,a,b,jz[1009][1009],mx[1009][1009],ans=2147483647,mn[1009][1009];
    deque<int> q[3];//q[1]:最大值,q[2]:最小值
    void push(int opt,int ps,int i){
    	if(opt==1){
    		while(!q[1].empty()&&jz[i][q[1].back()]<jz[i][ps]) q[1].pop_back();
    		q[1].push_back(ps);
    	}
    	if(opt==2){
    		while(!q[2].empty()&&jz[i][q[2].back()]>jz[i][ps]) q[2].pop_back();
    		q[2].push_back(ps);
    	}
    	if(opt==3){
    		while(!q[1].empty()&&mx[q[1].back()][i]<mx[ps][i]) q[1].pop_back();
    		q[1].push_back(ps);
    	}
    	if(opt==4){
    		while(!q[2].empty()&&mn[q[2].back()][i]>mn[ps][i]) q[2].pop_back();
    	    q[2].push_back(ps);
    	}
    }
    int main()
    {
       a=read();b=read();n=read();
       for(int i=1;i<=a;i++) for(int j=1;j<=b;j++) jz[i][j]=read();
       for(int i=1;i<=a;i++){//按行维护
       	   while(!q[1].empty()) q[1].pop_front();//把上一行的清空
       	   while(!q[2].empty()) q[2].pop_front();
       	   for(int j=1;j<n;j++) push(1,j,i),push(2,j,i);
    	   for(int j=n;j<=b;j++){
    	   	  while(!q[1].empty()&&q[1].front()<j-n+1) q[1].pop_front();
    	   	  while(!q[2].empty()&&q[2].front()<j-n+1) q[2].pop_front();
    	   	  push(1,j,i);push(2,j,i);
    	   	  mx[i][j-n+1]=jz[i][q[1].front()];
    	   	  mn[i][j-n+1]=jz[i][q[2].front()];
    
    	   }
       }
       for(int i=1;i<=b-n+1;i++){//因为只有[1,b-n+1]之间的列有mx,mn值,所以只循环到b-n+1
        while(!q[1].empty()) q[1].pop_front();//清空上一列
        while(!q[2].empty()) q[2].pop_front();
       	for(int j=1;j<n;j++) push(3,j,i),push(4,j,i);
       	for(int j=n;j<=a;j++){
       		while(!q[1].empty()&&q[1].front()<j-n+1) q[1].pop_front();
       		while(!q[2].empty()&&q[2].front()<j-n+1) q[2].pop_front();
       		push(3,j,i);push(4,j,i);
       		ans=min(ans,mx[q[1].front()][i]-mn[q[2].front()][i]);
    	   }
       }
       printf("%d
    ",ans);
    }
    
  • 相关阅读:
    ExtJS的定时任务(转)
    Web开发系列–GIS(转)
    Windows Mobile 6.0模拟器的浏览器中不能访问本机网址
    JS定时保存表单数据(UserData 行为)
    查询Sqlserver数据库死锁的一个存储过程(转)
    ExtJS4.0在IE9中出现了SCRIPT5007: 无法获取属性“flex”的值
    Microsoft Device Emulator 模拟器菜单 中文
    错误:网站辅助进程已被 IIS 终止(Debug 时是不是弹出)
    集成验证时IE采用Kerberos 还是NTLM验证方式?(摘抄)
    SQLServer 2005死锁终极大法(自动杀) 转
  • 原文地址:https://www.cnblogs.com/lcez56jsy/p/13510048.html
Copyright © 2011-2022 走看看