洛谷 P1371 NOI元丹

题目描述
小A打算开始炼NOI元丹(什么鬼),据说吃了可以提高NOI时的成绩。
是这么练的。元丹有三种元核,’N’,’O’,’I’。现有很多个这样原核,按顺序排成一行。炼元丹时,从左往右分别挑出’N’,’O’,’I’三个原核吞下。
现在他关心,有几种服用方式……且慢!
他觉得服用方式太少,以至于不能成仙。所以他可以通过某个途径,得到’N’,’O’,’I’的三种原核中的任意一个,至于哪一种由他决定。然后他将获得这个原核的插入到这一排原核中的任意位置(包括最前最后)。
现在你要知道,新的元核序列中能有多少种’N’,’O’,’I’的取出方式。子串的字母并不要求连续。


【题目分析】
枚举。


【代码】

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
int f[100010],g[100010],o[100010]; //从前往后的n的前缀和, g的后缀和,是不是o 
char s[100010];
int l;
int main()
{
    scanf("%d",&l);
    scanf("%s",s+1);
    for (int i=1;i<=l;++i)
    {
        f[i]=f[i-1];
        if (s[i]=='O') o[i]=1;
        if (s[i]=='N') f[i]++;
        if (s[i]=='I') g[i]++;
    }
    for (int i=l;i>=1;--i) g[i]+=g[i+1];
    long long ans=0;
    long long tmp=0;
    for (int i=1;i<=l;++i)
        if (o[i]) tmp+=((ll)f[i]+1)*(ll)g[i];
//    printf("put a N before ans is %lld\n",tmp);
    ans=max(ans,tmp);
    tmp=0;
    for (int i=1;i<=l;++i)
        if (o[i]) tmp+=(ll)f[i]*((ll)g[i]+1);
//    printf("put a I behind ans is %lld\n",tmp); 
    ans=max(ans,tmp);
    tmp=0;
    for (int i=1;i<=l;++i)
        if (o[i]) tmp+=(ll)g[i]*(ll)f[i];
//    printf("nothing is %lld\n",tmp);
    long long maxx=0;
    for (int i=1;i<=l;++i) maxx=max(maxx,(ll)f[i]*(ll)g[i]);
    tmp+=maxx;
    ans=max(ans,tmp);
//    printf("put a O in is %lld\n",tmp);
    printf("%lld\n",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值