郊游
(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; }