Finales E. Matrix 2020

https://nanti.jisuanke.com/t/49109

Apprenez de https://www.cnblogs.com/BOZHAO/p/13880947.html

Pour trouver le maximum de toutes les 1 sous-matrice, vous pouvez ouvrir à gauche et à droite pour trouver la largeur maximale correspondant à la hauteur

Mais parfois, cela implique de compter au milieu des 1 sous-matrices, qui doivent être laissées ouvertes et fermées à droite, c'est-à-dire que le côté gauche est strictement plus petit que le côté droit <=

Dans cette question, nous comptons le nombre de matrices qui doivent passer par (i, j) comme le bord inférieur de la i-ème ligne

Pour la hauteur la plus élevée h [j], la limite gauche est l [j], et la limite droite est r [j], nous pouvons d'abord obtenir (r [j] -l [j] +1) * h [j] tout ce Toutes les sous-matrices de la matrice qui remplissent les conditions, car il faut les compter pour passer (i, j), il faut soustraire les deux parties avec la hauteur la plus élevée h [j] qui ne passent pas (i, j), les largeurs sont respectivement jl [j] et r [j] -j

b [i] [j] signifie qu'il doit passer par (1,1), combien de sous-matrices de la matrice i * j satisfont aux exigences, alors somme [i] [j] signifie qu'il doit passer par (1,1) (1, 2) ... (1, j) la somme des sous-matrices qui remplissent les conditions

J'ai l'impression que cette non-répétition est un peu difficile à expliquer, je ne peux que faire un dessin pour comprendre pourquoi il n'y a pas de répétition. . . . Recommander 2323213 cette séquence de hauteur pour comprendre

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=1010;

int n,top;ll ans;
int h[maxl],s[maxl],l[maxl],r[maxl];
int a[maxl][maxl];
ll b[maxl][maxl],sum[maxl][maxl];
char c[maxl];

inline void prework()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",c+1);
		for(int j=1;j<=n;j++)
			a[i][j]=c[j]-'0';
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		if(i%j==0 || j%i==0)
			b[i][j]=1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			sum[i][j]=sum[i][j-1]+b[i][j];
}

inline void mainwork()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
			h[j]=(a[i][j]>0)?h[j]+1:0;
		s[0]=0;top=0;
		for(int j=1;j<=n;j++)
		{
			while(top>0 && h[s[top]]>=h[j])
				top--;
			l[j]=s[top]+1;
			s[++top]=j;
		}
		s[0]=n+1;top=0;
		for(int j=n;j>=1;j--)
		{
			while(top>0 && h[s[top]]>h[j])
				top--;
			r[j]=s[top]-1;
			s[++top]=j;
		}
		for(int j=1;j<=n;j++)
			ans+=sum[h[j]][r[j]-l[j]+1]-sum[h[j]][j-l[j]]-sum[h[j]][r[j]-j];
	}
}

inline void print()
{
	printf("%lld\n",ans);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

 

 

Je suppose que tu aimes

Origine blog.csdn.net/liufengwei1/article/details/109348408
conseillé
Classement