【题解】勇者比太郎

题目来源:loj
在这里插入图片描述

思路:

题目的意思就是先找到一个J,然后往这一行的后面找O的个数cnto,往这一列的下面找I的个数cnti,那么这个J对应的方案个数就是cnt0*cnti,总方案个数就是总的J对应的方案个数

怎么求这个J下面及后面的O和J的个数?可以用两个后缀和数组来找
寻找J的时间复杂度为O(h*w),查找时间只需要O(1),不会超时

后缀数组是什么?emmm…
那就前缀数组吧

code:

#include<bits/stdc++.h>
using namespace std;
const int N=3010;
long long n,m,O[N][N],I[N][N],anss,cnto,cnti;
//O[i][j]:前i行j列总共有多少个O
//I[i][j]:前i行j列总共有多少个I 
char a[N][N];
int main()
{
	scanf("%lld%lld",&n,&m);
	for (int i=1;i<=n;i++)
	  for (int j=1;j<=m;j++) 
	  {
	  	  cin>>a[i][j];
	  	  O[i][j]+=O[i][j-1]+O[i-1][j]+(a[i][j]=='O')-O[i-1][j-1];//O的前缀和 
		  I[i][j]+=I[i][j-1]+I[i-1][j]+(a[i][j]=='I')-I[i-1][j-1];//I的前缀和 
	  }
	  
	for (int i=1;i<=n;i++)
	  for (int j=1;j<=m;j++)
	  {
	  	if (a[i][j]=='J')  //找到J了 
	  	{
	  		cnto=O[i][m]-O[i][j-1]-O[i-1][m]+O[i-1][j-1]; //J的下面有多少个O 
	  		cnti=I[n][j]-I[n][j-1]-I[i-1][j]+I[i-1][j-1];//J的右边有多少个I 
	  	    anss+=cnto*cnti;//更新方案数 
	  	}
	  }
	printf("%lld\n",anss);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章