COCI 2018/2019 Strah(極大子矩形思想)

Everyone is afraid of something. Someone is afraid of darkness, someone is afraid of heights,
someone is afraid of Vinnie Jones (all of us are afraid of Vinnie Jones), someone is afraid of singing
before eating something…
There are many fears, but the greatest among all for Mirko is choosing a land for planting
strawberries. Mirko’s land can be described as a matrix with ​N rows and ​M columns. Some of the
fields in the matrix are suitable for planting strawberries and some are not – weeds grow there. Mirko
is looking for rectangular parts of the land that are completely filled with fields suitable for strawberry
planting. Those kind of rectangles are called suitable rectangles. Also, Mirko is interested in the
potential value of all fields in the matrix. The potential value of each field in the matrix is defined as
the number of suitable rectangles that contain that field.
Since Mirko has troubles facing his fears, he asks you to only calculate the sum of all the fields’
potential values.

含有’#'的矩形不合法
求每一個點被多少個合法矩形覆蓋,再求所有點的這個值總和。















一轉化就發現答案就是 所有合法矩形的面積和。
然後就枚舉矩形的下邊界,然後用單調隊列枚舉極大子矩形,再利用極大子矩形的關係巧妙的統計答案。
極大子矩形的單調隊列做法,業界已有諸多研究,就不在此贅述了。

AC code:

#include<cstdio>
#include<algorithm>
#include<queue>
#define LL long long
#define maxn 2005
using namespace std;

deque<int>q;
int h[maxn],n,m;
LL ans;
char mp[maxn][maxn];

inline LL sum(LL a1,LL an,LL n)
{
	return (a1+an) * n / 2;
}

int main()
{
	
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%s",mp[i]+1),
		mp[i][m+1] = '#';
		
	
	for(int i=1;i<=n;i++)
	{
		for(;!q.empty();q.pop_front());
		q.push_back(0);
		h[0] = i;
		for(int j=1;j<=m+1;j++) 
		{
			if(mp[i][j] == '#') h[j] = i;
			
			int tmp = 0;
			for(;!q.empty() && h[q.back()] <= h[j];q.pop_back())
			{
				int x = q.back();
				
				LL res = sum(i-tmp,i-h[q.back()]+1,h[q.back()]-tmp);
				ans += 1ll * (j - x - 1) * (j - x) * (j - x + 1) / 6 * res;
				
				tmp = max(tmp , h[q.back()]);
			}
			
			if(!q.empty())
			{
				int x = q.back();
				LL res = sum(i-tmp,i-h[j]+1,h[j]-tmp);
				ans += 1ll * (j - x - 1) * (j - x) * (j - x + 1) / 6 * res;
			}
			
			q.push_back(j);
		}	
	}
	printf("%lld\n",ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章