您的位置:首页 > 其它

[BZOJ2228][Zjoi2011][单调队列]礼物(gift)

2017-03-12 22:07 274 查看

题意

在一个p*q*r的正方体内找到一个a*a*b的子正方体,满足子正方体内均为N,求最大的4ab

考虑以一个面作为底面,可以正方体中每个点为左下角的正方形的边长(正方面平行于底面),然后考虑同一列中的点,可以把问题就转化成求一个序列,序列的最小值和区间长度相乘的结果最小。用单调队列做。

转动下正方体就可以计算所有情况啦

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#define N 210

using namespace std;

char w[N*N]
;
char A

,B

;
int p,q,r,t,Ans=0;
int bianc

;
int Q
,f
;

inline void Checking(){
memset(bianc,0,sizeof(bianc));
for(int k=1;k<=r;k++)
for(int i=1;i<=p;i++)
for(int j=1;j<=q;j++)
if(A[i][j][k]=='N')
bianc[i][j][k]=min(min(bianc[i][j-1][k],bianc[i-1][j][k]),bianc[i-1][j-1][k])+1;
for(int i=1;i<=p;i++)
for(int j=1;j<=q;j++){
Q[t=0]=0; bianc[i][j][0]=-1;
for(int k=1;k<=r;k++){
while(t&&bianc[i][j][k]<=bianc[i][j][Q[t]]) t--;
if(A[i][j][k]=='N') f[k]=k-Q[t]; else f[k]=0;
Q[++t]=k;
}
Q[t=0]=r+1; bianc[i][j][r+1]=-1;
for(int k=r;k;k--){
while(t&&bianc[i][j][k]<=bianc[i][j][Q[t]]) t--;
if(A[i][j][k]=='N') f[k]+=Q[t]-k;
Q[++t]=k;
}
for(int k=1;k<=r;k++) Ans=max(Ans,4*bianc[i][j][k]*(f[k]-1));
}
}

inline void Changing(){
for(int i=1;i<=p;i++)
for(int j=1;j<=q;j++)
for(int k=1;k<=r;k++)
B[j][k][i]=A[i][j][k];
int k=p; p=q; q=r; r=k;
for(int i=1;i<=p;i++)
for(int j=1;j<=q;j++)
for(int k=1;k<=r;k++)
A[i][j][k]=B[i][j][k];
}

int main(){
scanf("%d%d%d",&p,&q,&r);
for(int i=1;i<=p*q;i++) scanf("%s",w[i]+1);
for(int i=1;i<=p;i++)
for(int j=1;j<=q;j++)
for(int k=1;k<=r;k++) A[i][j][k]=w[j*p+i-p][k];
Checking();
Changing();
Checking();
Changing();
Checking();
printf("%d\n",Ans);
return 0;
}


跑的好慢啊……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: