洛谷P2216 [HAOI2007]理想的正方形

吐槽:重装系统重装了chrome它就把我博客园的账号和密码给忘了。然后我还不知道用哪个邮箱注册的,找了一上午才找回来。

题目链接

题意概述:选一个子矩阵使最大值-最小值尽量小。

先考虑n^4暴力……很好写然后T到天上去。然后考虑对每行建st表……还是T到天上去。最后考虑建个二维st表……就好了。

#include<cstring>
#include<iostream>
#include<cctype>
#include<cstdio>
#include<algorithm>
using namespace std;
int read()
{
    int X=0;char ch=0;bool flag=0;
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') flag=1;
    for(;isdigit(ch);ch=getchar()) X=(X<<3)+(X<<1)+ch-'0';
    return (flag ? -X : X);
}
void write(int x)
{
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int a,b,n,s[1001][1001][15],t[1001][1001][15],ans=2147483644,log[1001];
int mx(int a,int b,int c,int d)
{if(b>a)a=b;if(c>a)a=c;if(d>a)a=d;return a;}
int mn(int a,int b,int c,int d)
{if(b<a)a=b;if(c<a)a=c;if(d<a)a=d;return a;}
void st()
{
    int lim=log[min(a,b)];
    for(int k=1;k<=lim;k++)
        for(int i=1;i<=a-(1<<k)+1;i++)
            for(int j=1;j<=b-(1<<k)+1;j++)
            s[i][j][k]=mx(s[i][j][k-1],s[i][j+(1<<k-1)][k-1],
            s[i+(1<<k-1)][j][k-1],s[i+(1<<k-1)][j+(1<<k-1)][k-1]),
            t[i][j][k]=mn(t[i][j][k-1],t[i][j+(1<<k-1)][k-1],
            t[i+(1<<k-1)][j][k-1],t[i+(1<<k-1)][j+(1<<k-1)][k-1]);
}
int qu(int x,int y,int x1,int y1)
{
    int k=log[n],xx=0,mm=2e9;
    xx=mx(s[x][y][k],s[x][y1-(1<<k)+1][k],
    s[x1-(1<<k)+1][y][k],s[x1-(1<<k)+1][y1-(1<<k)+1][k]);
    mm=mn(t[x][y][k],t[x][y1-(1<<k)+1][k],
    t[x1-(1<<k)+1][y][k],t[x1-(1<<k)+1][y1-(1<<k)+1][k]);
    return xx-mm;
}
int main()
{
    a=read(),b=read(),n=read();
    log[0]=-1;for(int i=1;i<=a+b;i++) log[i]=log[i>>1]+1;
    for(int i=1;i<=a;i++)
        for(int j=1;j<=b;j++)
            s[i][j][0]=t[i][j][0]=read();
    st();
    for(int i=1;i<=a-n+1;i++)
        for(int j=1;j<=b-n+1;j++)
            ans=min(ans,qu(i,j,i+n-1,j+n-1));
    write(ans);
}

 

posted @ 2018-09-12 10:53  _hcy_a  阅读(184)  评论(4编辑  收藏  举报