2250. NOIP

2250. NOIP

题目描述
你知道New Orange Industry Palatable公司吗?这是老板Smart为了与苹果公司竞争而新开的一家橘子公司,它的业务是栽培美味的橘子并售卖,公司简称为NOIP。 NOIP公司新推出N+1个橘子,每个橘子上都贴有一个标签,其中有N个普通的橘子上面印有一个"N"或"O"或"I"字母。还有一个独一无二的幸运橘子标签印有"P"字母。 NOIP公司搞了一个优惠活动,把N个普通橘子排成一排,从左到右依次编号为1~N。让顾客从左到右选三个橘子,如果依次排列组成了"NOI",就可获得优惠券。Smart想把贴有标签P的幸运橘插入到排列中的(可以插入到队列的任意位置)。在换取优惠券时,P橘子可以作为N橘子或O橘子或I橘子使用。Smart想知道加入P橘子以后,第一个选购的顾客最多有多少种选法可以得到优惠券。

输入
第一行是一个整数N,表示NOIP公司有N个普通橘子。
第二行是一个长度为N的字符串S,仅由N,O,I三个大写英文字母组成。字符串的左数第i个字母表示第i个橘子的标签类型。

输出
输出为一行,表示选择方式的最大值。

样例输入
样例输入1

5
NOIOI

样例输入2

7
NNNOIII

样例输出
样例输出1

6

样例输出2

18

数据范围限制
30%的数据:3≤N≤20;
60%的数据:3≤N≤200;
80%的数据:3≤N≤3000;
100%的数据:3≤N≤100000。

提示
样例1中将"P"放在"NOIOI"中"N"前一个位置或后一个位置,并将"P"作为N橘子使用,最多有6种选法可以得到优惠券。
样例2中将"P"放在" NNNOIII "中"O"前一个位置或后一个位置,并将"P"作为O橘子使用,最多有18种选法可以得到优惠券。

思路:
我们用f[0][i]表示前i个字符中有多少个‘N’;f[1][j]表示前i个字符中有多少个‘O’,f[2][i]表示前i个字符中有多少个‘I’.(前缀和)

然后模拟在第i位把‘P’当做‘N’,‘O’,‘I’插入的情况(取MAX),最后加上不插‘P’的方案数。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=1e6;
char s[100100];
long long n,f[3][100100],a,b,c,d,ans;
int main()
{
	fre(noip);
	scanf("%d",&n);
	char hc=getchar();
	for(int i=1;i<=n;i++) 
	{
		cin>>s[i];	
		if(s[i]=='N') f[0][i]=f[0][i-1]+1;
			else f[0][i]=f[0][i-1];
		if(s[i]=='O') f[1][i]=f[1][i-1]+1;
			else f[1][i]=f[1][i-1];
		if(s[i]=='I') f[2][i]=f[2][i-1]+1;
			else f[2][i]=f[2][i-1];
	}
	for(int i=1;i<=n;i++)
	{
		if(s[i]=='N') a+=f[1][n]-f[1][i];
		if(s[i]=='O') b+=f[0][i]*(f[2][n]-f[2][i]);
		if(s[i]=='I') c+=f[1][i];
		d=max(d,f[0][i-1]*(f[2][n]-f[2][i-1]));
	}
	ans=max(a,max(c,d));
	printf("%lld",ans+b);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/bigwinner888/article/details/107141953