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

    题目传送门
    xfz学长给我们讲了单调栈和单调队列,这方面内容以前写过PJT4的跳房子等等。
    事实上单调栈和单调队列挺好理解的,单调栈是栈内元素单调的栈,单调队列是队内元素单调的队列(废话)
    先写一道非常裸的模板题。这道题以最大值为例,先一次单调队列求出每一行每个位置向右连续n个数的最大值,再一次单调队列把之前求出的一维最大值用同样的方法和并为二维最大值。单调队列实现方法就是先把左端点不在当前考虑区间内的丢掉,再比较当前位置与队尾的大小,若大于等于则把队尾丢掉,把当前位置的元素放进去。求出最大值和最小值最后统计即可。细节详见代码。(其实没啥细节,我这样的菜鸡也能1A)

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=1005;
    int n,m,x,head,tail,ans=1e9,q[N],a[N][N],f[N][N],maxn[N][N],minn[N][N];
    int main(){
        scanf("%d%d%d",&n,&m,&x);
        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=1,tail=0;
            for(int j=1;j<=x;j++){
                while(head<=tail&&a[i][j]>=a[i][q[tail]]){
                    tail--;
                }
                q[++tail]=j;
            }
            f[i][1]=a[i][q[head]];
            for(int j=x+1;j<=m;j++){
                while(head<=tail&&q[head]<j-x+1){
                    head++;
                }
                while(head<=tail&&a[i][j]>=a[i][q[tail]]){
                    tail--;
                }
                q[++tail]=j;
                f[i][j-x+1]=a[i][q[head]];
            }
        }
        for(int i=1;i<=m-x+1;i++){
            head=1,tail=0;
            for(int j=1;j<=x;j++){
                while(head<=tail&&f[j][i]>=f[q[tail]][i]){
                    tail--;
                }
                q[++tail]=j;
            }
            maxn[1][i]=f[q[head]][i];
            for(int j=x+1;j<=n;j++){
                while(head<=tail&&q[head]<j-x+1){
                    head++;
                }
                while(head<=tail&&f[j][i]>=f[q[tail]][i]){
                    tail--;
                }
                q[++tail]=j;
                maxn[j-x+1][i]=f[q[head]][i];
            }
        }
        for(int i=1;i<=n;i++){
            head=1,tail=0;
            for(int j=1;j<=x;j++){
                while(head<=tail&&a[i][j]<=a[i][q[tail]]){
                    tail--;
                }
                q[++tail]=j;
            }
            f[i][1]=a[i][q[head]];
            for(int j=x+1;j<=m;j++){
                while(head<=tail&&q[head]<j-x+1){
                    head++;
                }
                while(head<=tail&&a[i][j]<=a[i][q[tail]]){
                    tail--;
                }
                q[++tail]=j;
                f[i][j-x+1]=a[i][q[head]];
            }
        }
        for(int i=1;i<=m-x+1;i++){
            head=1,tail=0;
            for(int j=1;j<=x;j++){
                while(head<=tail&&f[j][i]<=f[q[tail]][i]){
                    tail--;
                }
                q[++tail]=j;
            }
            minn[1][i]=f[q[head]][i];
            for(int j=x+1;j<=n;j++){
                while(head<=tail&&q[head]<j-x+1){
                    head++;
                }
                while(head<=tail&&f[j][i]<=f[q[tail]][i]){
                    tail--;
                }
                q[++tail]=j;
                minn[j-x+1][i]=f[q[head]][i];
            }
        }
        for(int i=1;i<=n-x+1;i++){
            for(int j=1;j<=m-x+1;j++){
                ans=min(ans,maxn[i][j]-minn[i][j]);
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    (6)UIView常见属性二
    linux系统中不间断会话服务screen命令
    linux系统中配置sshd服务(远程控制服务)
    Linux系统中远程传输命令scp
    linux系统中防火墙管理工具iptables
    什么是端口?
    linux系统实现会话共享功能
    linux系统中远程控制服务安全密码验证 sshkeygen命令
    linux系统中防火墙策略管理工具firewalld
    linux系统中nmcli命令、查看、添加、删除、编辑网络会话
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476894.html
Copyright © 2011-2022 走看看