题解:SP6517 JOCHEF - Farmer Sepp

一眼简单悬线法,而且有多倍经验,感觉这题被遗忘了,那我就拿下这个水紫吧!

我们用 a 数组表示能向上延伸能到达的最大距离,依次遍历每一行,如果该位置为 F,他可以从上一行转移过来,将a数组增加一,如果该位置为 C,意味着这个位置不能成矩形,将 a 数组变为 0。

接下来进行悬线法的标准操作,设 l 数组为能向左延伸到不低于此位置的高度的最远位置,然后进行推导。

  • \(i=1\),到达边界停止。

  • \(a[i]>a[i-1]\),低于高度,停止拓展。

  • \(a[i]<=a[i-1]\),可以扩展,直接继承 \(l[i]=l[l[i]-1]\)

r 数组则是向右延伸,相同方法赋值即可,最后统计答案直接将高度乘上可延伸的长度,结果取最大值一气呵成。

运行过程类似下图(其他题的图片但同一个意思)。

image

注意这题有多组数据,换行与多测清空都要注意。

上代码!!!

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e4+10;
#define int ll
int n,m,k;
int a[N];
int l[N],r[N];
int ans;
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while(1){
    	cin>>n>>m;
    	
    	if(n==m&&n==0){
    		break;
		}
		ans=0;
		memset(a,0,sizeof a);
		cin>>k;
	    for(int i=1;i<=n;i++){
	    	for(int j=1;j<=m;j++){
	    		l[j]=r[j]=j;
			}
			char c;
			for(int j=1;j<=m;j++){
				cin>>c;
				if(c=='C'){
					a[j]=0;
				}
				else if(c=='H'){
					a[j]++;
				}
			}
			for(int j=1;j<=m;j++){
				while(l[j]!=1&&a[j]<=a[l[j]-1]){
					l[j]=l[l[j]-1];
				}
			}
			for(int j=m;j>=1;j--){
				while(r[j]!=m&&a[j]<=a[r[j]+1]){
					r[j]=r[r[j]+1];
				}
			}
			for(int j=1;j<=m;j++){
				ans=max(ans,a[j]*(r[j]-l[j]+1));
			}
		}
	    cout<<(ll)ans*k<<"\n";
	}
    return 0;
}
posted @ 2024-10-09 15:04  sad_lin  阅读(2)  评论(0编辑  收藏  举报