郊游
郊游
(1 s ,128 MB, trip .cpp/c/pas )【问题描述】
小朋友们出去郊游,明明和亮亮负责在草地上开一个篝火晚会。这个草地你可以认为是由N * M 块单位长度为 1 的小正方形的草组成。
显然有的地方草长的好,有的地方长的不好,坐在上面显然舒服度是不一样的,于是每一
块草都有一个舒服度 F。
现在明明和亮亮要选定一个 a*b 的草场作为晚会的地点,小朋友们就坐在上面,显然他希
望小朋友们坐的最舒服!
不过别急,篝火晚会怎么能少了篝火呢,篝火需要占用 c*d 的草地,当然,篝火必须严格
放置在选定的草地的内部,也就是说,篝火的边界不能和选定操场的边界有公共部分,不然学
生们怎么围着篝火开晚会呢?
给定 N*M 大草地每一块的舒服度,寻找一个 a*b 的草地,除去一个严格内部的 c*d 的
子草地,使得总的舒服度最大。
【 输入描述 】
第 1 行:6 个整数,M, N, b, a, d, c第 2~N+1 行:每行 M 个整数,第 i 行 j 列的整数 Fi,j 表示,第 i 行 j 列的单位草
地的舒服度。
【 输出描述 】
一个整数,表示最大的舒服值。【样例输入】
8 5 5 3 2 11 5 10 3 7 1 2 5
6 12 4 4 3 3 1 5
2 4 3 1 6 6 19 8
1 1 1 3 4 2 4 5
6 6 3 3 3 2 2 2
【样例输出】
70
【 样例说明 】
下面的图片就是对样例的解释,阴影区域就是最佳的选择方案。比如方案 4 1 4 1 就是显然非法的,因为篝火出现出现在了选定草地的边界,学生们无
法严格围住篝火。
【 数据规模 】
1 ≤ Fi,j ≤ 1003 ≤ a ≤ N
3 ≤ b ≤ M
1 ≤ c ≤ a-2
1 ≤ d ≤ b-2
对于 40% 的数据 N,M ≤ 10
对于 60% 的数据 N,M ≤ 150
对于 100% 的数据 N,M ≤ 1000
所用知识
前缀和,ST表,滑动窗口(单调队列)
c++代码
#include<bits/stdc++.h>
using namespace std;
int m,n,a,b,c,d;
int MAP;
int tot[1005][1005];
int gh[1005][1005];
int st[1005][1005][15];
int log_2[1005];
int ANS;
deque< int > v;
deque< int > y;
int main()
{
freopen("trip.in","r",stdin);
freopen("trip.out","w",stdout);
for(int i=1,ans=0;i<=1005;i++)//预处理 LOG2
{
if(i>=(1<<ans))
ans++;
log_2[i]=ans-1;
}
cin>>n>>m>>b>>a>>d>>c;
for(int i=1;i<=m;i++)
{
int all=0;
for(int j=1;j<=n;j++)
{
scanf("%d",&MAP);
all+=MAP;
tot[i][j]=tot[i-1][j]+all;//前缀和
}
}
for(int i=1;i<=m-c+1;i++)// st表
for(int j=1;j<=n-d+1;j++)
st[i][j][0]=tot[i+c-1][j+d-1]-tot[i-1][j+d-1]-tot[i+c-1][j-1]+tot[i-1][j-1];
for(int x=1;x<=10;x++)// st表初始化
for(int i=1;i<=m&&i+(1<<(x-1))<=n;i++)
for(int j=1;j<=n;j++)
st[i][j][x]=min(st[i][j][x-1],st[i+(1<<(x-1))][j][x-1]);
for(int i=1;i<=m-c+1;i++)
for(int j=1;j<=n-d+1;j++)
gh[i][j]=min(st[i][j][log_2[a-1-c]],st[i+a-1-c-(1<<log_2[a-1-c])][j][log_2[a-1-c]]);
for(int i=1;i<=m-a+1;i++)// 滑动窗口
{
while(v.size())
{
v.pop_back();
y.pop_back();
}
for(int j=2;j<b-d;j++)
{
while(v.size()&&gh[i+1][j]<=v.back())
{
v.pop_back();
y.pop_back();
}
v.push_back(gh[i+1][j]);
y.push_back(j);
}
for(int j=1;j<=n-b+1;j++)
{
int he=tot[i+a-1][j+b-1]-tot[i-1][j+b-1]-tot[i+a-1][j-1]+tot[i-1][j-1];
int now=gh[i+1][j+b-d-1];
while(v.size()&&now<=v.back())
{
v.pop_back();
y.pop_back();
}
v.push_back(now);
y.push_back(j+b-d-1);
while(y.front()<=j)
{
v.pop_front();
y.pop_front();
}
ANS=max(ANS,he-v.front());
}
}
cout<<ANS<<endl;
return 0;
} 