JZOJ 5417 方阵

来源:互联网 发布:scala编程思想 pdf下载 编辑:程序博客网 时间:2024/05/16 07:21

方阵

Description

给出一个n*m的矩形A,第i行第j列的值为Ai,j
给出q个询问,每次询问某个在A内的矩阵的最大值,最小值以及和。

Data Constraint

n,m<=800,q<=500000,0<=Ai,j<=3000,每个询问的方阵的长不超过宽的两倍

Solution

方法一
一看到这题直接上二维RMQ,但这样不仅会空间超限,预处理还会时间超限。
既然会空间超限,那就可以预处理少一点,只预处理到27,这样预处理空间时间都不会超限,同时询问的时候最多也只需用49个预处理好的RMQ平面来覆盖,整体时间复杂度控制在了可以过掉的范围内。

方法二
看到每个询问的方阵的长不超过宽的两倍,于是便可以只预处理以某个位置为右下角的边长为2k的正方形内的信息,这样一来一个方阵用8个正方形便可以覆盖掉。

Code(Solution 1)

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define fo(i,j,l) for(int i=j;i<=l;i++)#define fd(i,j,l) for(int i=j;i>=l;i--)#define mm 'M'#define xx 'X'#define nn 'N'using namespace std;typedef long long ll;const ll N=802,P=8,M=51e4;int n,m,j,k,l,i,o,qq;int a[N][N],q[N][N],f[N][N][P][P],xw[M][4],ans[M],m2[10],bl[N];int d1[2*P],d2[2*P];char c[M];int read(){    int a=0; char ch=' ';    for(;ch<'0'||ch>'9';)ch=getchar();    for(;ch>='0'&&ch<='9';ch=getchar())a=a*10+ch-48;    return a;}int min(int a,int b){if(a<b)return a;else return b;}int max(int a,int b){if(a>b)return a;else return b;}void pri(int o){if(!o)return; pri(o/10); putchar('0'+o%10);}void write(int o){    if(o>0)pri(o);else putchar('0');     putchar('\n');}int main(){    cin>>n>>m;    fo(i,1,n)fo(l,1,m)a[i][l]=read(),q[i][l]=q[i][l-1]+a[i][l];    fo(i,1,n)fo(l,1,m)q[i][l]+=q[i-1][l];    m2[0]=1; fo(i,1,9)m2[i]=m2[i-1]*2;    for(int k=0,i=1;i<=max(n,m);i++){        bl[i]=k;        if(i==m2[k]*2)k=min(k+1,P-1);    }    fo(i,1,n){        fo(l,1,m)f[i][l][0][0]=a[i][l];        fo(j,1,bl[m])        fo(l,1,m-m2[j]+1)        f[i][l][0][j]=min(f[i][l][0][j-1],f[i][l+m2[j-1]][0][j-1]);    }    fo(j,1,bl[n])    fo(i,1,n-m2[j]+1)    fo(k,0,bl[m])    fo(l,1,m-m2[k]+1)    f[i][l][j][k]=min(f[i][l][j-1][k],f[i+m2[j-1]][l][j-1][k]);    cin>>qq;    fo(i,1,qq){        for(c[i]='\n';c[i]=='\n';)c[i]=getchar();        c[i]=getchar(); c[i]=getchar();        xw[i][0]=read()+1,xw[i][1]=read()+1;        xw[i][2]=read()+1,xw[i][3]=read()+1;        if(c[i]==mm){            int x1=xw[i][0]-1,x2=xw[i][2],y1=xw[i][1]-1,y2=xw[i][3];            ans[i]=q[x2][y2]-q[x2][y1]-q[x1][y2]+q[x1][y1];        }        if(c[i]==nn)        {            ans[i]=q[n][m];            int x1=xw[i][0],x2=xw[i][2],y1=xw[i][1],y2=xw[i][3];            int r1=1,r2=1,o1=bl[x2-x1+1],o2=bl[y2-y1+1];            for(d1[1]=x1;d1[r1]+m2[o1]-1<x2;r1++)d1[r1+1]=d1[r1]+m2[o1];            d1[r1]=x2-m2[o1]+1;            for(d2[1]=y1;d2[r2]+m2[o2]-1<y2;r2++)d2[r2+1]=d2[r2]+m2[o2];            d2[r2]=y2-m2[o2]+1;            fo(l,1,r1)fo(j,1,r2)            ans[i]=min(ans[i],f[d1[l]][d2[j]][o1][o2]);        }    }    fo(i,1,n){        fo(l,1,m)f[i][l][0][0]=a[i][l];        fo(j,1,bl[m])        fo(l,1,m-m2[j]+1)        f[i][l][0][j]=max(f[i][l][0][j-1],f[i][l+m2[j-1]][0][j-1]);    }    fo(j,1,bl[n])    fo(i,1,n-m2[j]+1)    fo(k,0,bl[m])    fo(l,1,m-m2[k]+1)    f[i][l][j][k]=max(f[i][l][j-1][k],f[i+m2[j-1]][l][j-1][k]);    fo(i,1,qq)if(c[i]==xx)    {        ans[i]=0;        int x1=xw[i][0],x2=xw[i][2],y1=xw[i][1],y2=xw[i][3];        int r1=1,r2=1,o1=bl[x2-x1+1],o2=bl[y2-y1+1];        for(d1[1]=x1;d1[r1]+m2[o1]-1<x2;r1++)d1[r1+1]=d1[r1]+m2[o1];        d1[r1]=x2-m2[o1]+1;        for(d2[1]=y1;d2[r2]+m2[o2]-1<y2;r2++)d2[r2+1]=d2[r2]+m2[o2];        d2[r2]=y2-m2[o2]+1;        fo(l,1,r1)fo(j,1,r2)        ans[i]=max(ans[i],f[d1[l]][d2[j]][o1][o2]);    }    fo(i,1,qq)write(ans[i]);}
原创粉丝点击