Problem:
スタンプラリー２ (Collecting Stamps 2)
JOI 商店街には大通りに沿って $N$ 個の店があり，JOI 商店街の入口から出口に向かってそれぞれ $1, 2, ..., N$ の番号が付けられている．JOI 商店街は一方通行で，入口から出口方向へしか移動することはできない．
まちおこしのため，JOI 商店街でスタンプラリーを行うことになった．このスタンプラリーでは，それぞれの店はJ，O，I のいずれかのスタンプを用意し，店で買い物をした人はスタンプカードにスタンプを押してもらう．スタンプラリーに参加する人はちょうど 3 つの店に入る．商店街の入口では 3 つの欄のあるスタンプカードを配り，1 回目に入った店，2 回目に入った店，3 回目に入った店のスタンプを押してもらう．商店街の出口でスタンプカードを回収し，押されたスタンプが先に入った店のものから順にJ，O，Iになっているとき，出口で商品券がもらえるキャンペーンを実施することになった．押されたスタンプの種類や順番が異なるときは商品券はもらえない．
すでに $N$ 個のすべての店はどのスタンプを用意するか決めたが，新たに1 つの店をJOI 商店街に出すことになり，新しく出店する場所と，その店が用意するスタンプを決めることになった．新しい店を出す場所は，店 $i$ と店 $i + 1$ の間 $(1 \leq i \leq N - 1)$，入口と店 $1$ の間，店 $N$ と出口の間のいずれかから決める．また，新しい店のスタンプは J，O，I の 3 通りから決める．
商品券をもらえるような店の選び方の数が大きいほど，スタンプラリーが盛り上がると商店街は考えた．そこで，新しく出す店の場所と用意するスタンプを決めたときの，上記の店の選び方の数の最大値を求めたい．
課題
JOI 商店街のすでにある店が用意したスタンプの情報が与えられたとき，新しく出す店の場所と用意するスタンプを決めたときの，商品券をもらえるような店の選び方の数の最大値を求めるプログラムを作成せよ．
入力
標準入力から以下の入力を読み込め．
1 行目には，1 つの整数 $N$ が書かれている．これは，JOI 商店街には現在 $N$ 個の店があることを意味する．
2 行目には，$N$ 文字の半角英大文字 J, O, I のみからなる文字列 $S$ が書かれている．文字列 $S$ の左から $i$ 文字目 $(1 \leq i \leq N)$ は，店 $i$ が用意したスタンプの種類を表す．
出力
商品券をもらえるような店の選び方の数の最大値を標準出力に 1 行で出力せよ．
商品券をもらえるような店の選び方の数が32 ビット符号付き整数の範囲に収まるとは限らないことに注意せよ．
制限
すべての入力データは以下の条件を満たす．
$3 \leq N \leq 100 000$
入出力例
入力例1
5
JOIOI
出力例1
6
入力例 1 では，店 1 と店 2 の間に，スタンプ J を用意する新しい店を出したとき，店が用意したスタンプを入口から順に並べると JJOIOI となる．
このとき，商品券をもらえるような店の選び方は以下の 6 通りである．
1, 3, 4 番目の店に行く．
1, 3, 6 番目の店に行く．
1, 5, 6 番目の店に行く．
2, 3, 4 番目の店に行く．
2, 3, 6 番目の店に行く．
2, 5, 6 番目の店に行く．
入力例 1 において，商品券をもらえるような店の選び方が 7 通り以上になることはない．
入力例2
7
JJJOIII
出力例2
18
入力例3
4
OIIJ
出力例3
2
入力例 3 では，入口と店 1 の間にスタンプ J を用意する新しい店を出したとき，商品券をもらえるような店の選び方の数が最大となる．
第15回 日本情報オリンピック本選 課題   2016 年 2 月 14 日

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
#define rep(i,n) for(ll i=0;i<n;i++)
#define all(A) A.begin(),A.end()
ll M=0;
ll solve(string S){
    vll J,I;
    ll N=S.size();
    rep(i,N){
        if(S[i]=='J')J.push_back(i);
        if(S[i]=='I')I.push_back(i);
    }
    ll an=0;
    rep(i,N){
        ll p=lower_bound(all(J),i)-J.begin();
        ll q=I.end()-lower_bound(all(I),i);
        M=max(M,p*q);
        if(S[i]=='O'){
            
            an+=p*q;
        }
    }
    return an;
}

int main() {
    ll N;
    string S;
    cin>>N>>S;
    ll an=solve(S);
    an+=M;
    string T="J"+S;
    an=max(an,solve(T));
    T=S+"I";
    an=max(an,solve(T));
    cout<<an<<endl;
}
accuracy: 1
time_ms: 20
memory_kb: 5212
final_rank: 4

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
constexpr int INF = 0x3f3f3f3f;
constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr double EPS = 1e-8;
constexpr int MOD = 1000000007;
// constexpr int MOD = 998244353;
constexpr int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
constexpr int dy8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx8[] = {0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
struct IOSetup {
  IOSetup() {
    std::cin.tie(nullptr);
    std::ios_base::sync_with_stdio(false);
    std::cout << fixed << setprecision(20);
  }
} iosetup;

int main() {
  int n; string s; cin >> n >> s;
  map<char, int> mp{{'J', 0}, {'O', 1}, {'I', 2}};
  vector dp1(n + 1, vector(3, 0LL));
  dp1[0][0] = 1;
  REP(i, n) REP(j, 3) {
    dp1[i + 1][j] += dp1[i][j];
    if (j + 1 < 3 && mp[s[i]] == j) dp1[i + 1][j + 1] += dp1[i][j];
  }
  vector dp2(n + 1, vector(3, 0LL));
  dp2[n][2] = 1;
  for (int i = n - 1; i >= 0; --i) REP(j, 3) {
    dp2[i][j] += dp2[i + 1][j];
    if (j > 0 && mp[s[i]] == j) dp2[i][j - 1] += dp2[i + 1][j];
  }
  vector<int> js(n + 1, 0), ji(n + 1, 0);
  REP(i, n) js[i + 1] = js[i] + (s[i] == 'J');
  for (int i = n - 1; i >= 0; --i) ji[i] = ji[i + 1] + (s[i] == 'I');
  ll ans = 0;
  REP(i, n + 1) {
    chmax(ans, dp2[i][0]);  // J
    chmax(ans, 1LL * js[i] * ji[i]);  // O
    chmax(ans, dp1[i][2]);  // I
  }
  vector dp3(n + 1, vector(4, 0LL));
  dp3[0][0] = 1;
  REP(i, n) REP(j, 4) {
    dp3[i + 1][j] += dp3[i][j];
    if (mp[s[i]] == j) dp3[i + 1][j + 1] += dp3[i][j];
  }
  cout << ans + dp3[n][3] << '\n';
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 22088
final_rank: 15

code_snippet: #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<math.h>
#include<string>
#include<string.h>
#include<stack>
#include<queue>
#include<vector>
#include<utility>
#include<set>
#include<map>
#include<stdlib.h>
#include<iomanip>

using namespace std;

#define ll long long
#define ld long double
#define EPS 0.0000000001
#define INF 1e9
#define LINF (ll)INF*INF
#define MOD 1000000007
#define rep(i,n) for(int i=0;i<(n);i++)
#define loop(i,a,n) for(int i=a;i<(n);i++)
#define all(in) in.begin(),in.end()
#define shosu(x) fixed<<setprecision(x)

#define int ll //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int,int> pii;
typedef vector<pii> vp;

int gcd(int a, int b){
    if(b==0) return a;
    return gcd(b,a%b);
}
int lcm(int a, int b){
    return a/gcd(a,b)*b;
}


signed main(void) {
    int n;
    cin >> n;
    string s;
    cin >> s;
    string t = "JOI";
    vector<vi> dp(n+1,vi(4,0));
    dp[0][0] = 1;
    rep(i,n)rep(j,4){
        dp[i+1][j] += dp[i][j];
        if(j < 3 && s[i] == t[j])dp[i+1][j+1] += dp[i][j];
    }
    int ans = dp[n][3];
    reverse(all(s));
    reverse(all(t));
    vector<vi> dp1(n+1,vi(4,0));
    dp1[0][0] = 1;
    rep(i,n)rep(j,4){
        dp1[i+1][j] += dp1[i][j];
        if(j < 3 && s[i] == t[j])dp1[i+1][j+1] += dp1[i][j];
    }
    int ma = 0;
    ma = dp1[n][2];//先頭にJ
    rep(i,n){//s[i]とs[i+1]のあいだに入れる
        int l = n-i;
        ma = max(ma,dp1[l][2]);//J
        ma = max(ma,dp[i][1]*dp1[l][1]);//O
        ma = max(ma,dp[i+1][2]);//I
    }
    cout << ans + ma << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 17160
final_rank: 14

code_snippet: //h16-2 スタンプラリー2(解き直し)
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <string>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <random>
#include <cassert>
using namespace std;
#include <boost/multiprecision/cpp_int.hpp>
namespace boost_multiprecision = boost::multiprecision;
#define LL long long
#define CINT boost_multiprecision::cpp_int
#undef INT_MIN
#undef INT_MAX
#define INT_MIN -2147483648
#define INT_MAX 2147483647
#define LL_MIN -9223372036854775807
#define LL_MAX 9223372036854775807
#define segment_size 65536
#define ROOP() while (true)

int N;
string S;

vector<int> J;
vector<int> O;
vector<int> I;

int main(){

    cin >> N >> S;

    for(int i=0; i<N; i++){
        if(S[i] == 'J'){
            J.push_back(i);
        }
        if(S[i] == 'O'){
            O.push_back(i);
        }
        if(S[i] == 'I'){
            I.push_back(i);
        }
    }

    LL sum = 0;
    for(int i=0; i<O.size(); i++){
        auto itr = lower_bound(J.begin(), J.end(), O[i]);
        int a = itr - J.begin();
        auto itr2 = lower_bound(I.begin(), I.end(), O[i]);
        int b = itr2 - I.begin();
        b = I.size() - b;
        sum += a * b;
    }

    LL ans = 0;

    //O
    for(int i=0; i<N+1; i++){
        auto itr = lower_bound(J.begin(), J.end(), i);
        int a = itr - J.begin();
        auto itr2 = lower_bound(I.begin(), I.end(), i);
        int b = itr2 - I.begin();
        b = I.size() - b;
        ans = max(ans, sum + a*b);
        //cout << sum + a*b << endl;
    }

    //J
    LL tmp = 0;
    J.insert(J.begin(), -1);
    for(int i=0; i<O.size(); i++){
        auto itr = lower_bound(J.begin(), J.end(), O[i]);
        int a = itr - J.begin();
        auto itr2 = lower_bound(I.begin(), I.end(), O[i]);
        int b = itr2 - I.begin();
        b = I.size() - b;
        tmp += a * b;
    }
    J.erase(J.begin());
    ans = max(ans,tmp);
    //cout << tmp << endl;

    //I
    tmp = 0;
    I.push_back(N);
    for(int i=0; i<O.size(); i++){
        auto itr = lower_bound(J.begin(), J.end(), O[i]);
        int a = itr - J.begin();
        auto itr2 = lower_bound(I.begin(), I.end(), O[i]);
        int b = itr2 - I.begin();
        b = I.size() - b;
        tmp += a * b;
    }
    ans = max(ans,tmp);
    //cout << tmp << endl;

    cout << ans << endl;

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3776
final_rank: 2

code_snippet: //h16-2 スタンプラリー2
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <string>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <random>
#include <cassert>
using namespace std;
#include <boost/multiprecision/cpp_int.hpp>
namespace boost_multiprecision = boost::multiprecision;
#define LL long long
#define CINT boost_multiprecision::cpp_int
#undef INT_MIN
#undef INT_MAX
#define INT_MIN -2147483648
#define INT_MAX 2147483647
#define LL_MIN -9223372036854775807
#define LL_MAX 9223372036854775807
#define segment_size 65536
#define ROOP() while (true)

int N;
string S;
vector<int> J;
vector<int> O;
vector<int> I;

int place;
char moji;

vector<LL> J2;
LL O2[100000];
vector<LL> I2;

LL dp[100000];

LL solve(int now){
    if(now == -1){
        if(moji == 'I') return 1;
        if(moji == 'O') return I2[place];
        if(moji == 'J'){
            LL tmp = 0;
            auto itr = lower_bound(J.begin(), J.end(), place);
            if(itr != J.end()){
                tmp += dp[*itr];
                auto itr2 = lower_bound(O.begin(), O.end(), place);
                if(itr2 == O.end()) return 0;
                auto itr3 = lower_bound(O.begin(), O.end(), *itr);
                itr3--;
                if(itr2 != O.begin()){
                    itr2--;
                    tmp += O2[*itr3] - O2[*itr2];
                }
                else{
                    tmp += O2[*itr3];
                }
            }
            else{
                auto itr2 = lower_bound(O.begin(), O.end(), place);
                if(itr2 == O.end()) return 0;
                auto itr3 = O.end();
                itr3--;
                if(itr2 != O.begin()){
                    itr2--;
                    tmp += O2[*itr3] - O2[*itr2];
                }
                else{
                    tmp += O2[*itr3];
                }
            }
        
            return tmp;
        }
    }
    else{
        if(S[now] == 'I') return 1;
        if(S[now] == 'O') return I2[now];
        if(S[now] == 'J'){
            if(dp[now] != -1) return dp[now];
            LL tmp = 0;
            for(int i=0; i<O.size(); i++){
                if(O[O.size()-i-1] > now) tmp += I2[O[O.size()-i-1]];
                else break;
            }
            dp[now] = tmp;
            return tmp;
        }
    }
}

int main(){
    cin >> N;
    cin >> S;

    
    J2.push_back(0);
    I2.push_back(0);
    for(int i=0; i<N; i++){
        if(S[i] == 'J'){
            J.push_back(i);
            J2.push_back( J2.back()+1 );
        }
        else{
            J2.push_back( J2.back() );
        }
        if(S[i] == 'O') O.push_back(i);
        if(S[i] == 'I') I.push_back(i);

        if(S[N-i-1] == 'I') I2.push_back( I2.back() + 1);
        else I2.push_back( I2.back() );

        dp[i] = -1;
    }
    reverse(I2.begin(), I2.end());

    LL tmp = 0;
    auto itr = O.begin();
    while(itr != O.end()){
        tmp += I2[*itr];
        O2[*itr] = tmp;
        itr++;
    }

    place = -1;
    moji = 'X';
    vector<LL> sum;
    sum.push_back(0);
    for(int j=0; j<J.size(); j++){
        sum.push_back( sum.back() + solve(J[j]) );
    }

    vector<LL> J3;
    tmp = 0;
    for(int i=0; i<N; i++){
        J3.push_back(0);
        if(S[i] == 'O'){
            tmp += J2[i];
            J3.back() = tmp;
        }
    }

    LL ans = 0;
    for(int i=0; i<N+1; i++){ //iはそれより1つ前を指す
        place = i;

        moji = 'J';
        ans = max(ans, sum.back() + solve(-1));

        moji = 'O';
        ans = max(ans, sum.back() + J2[i+1] * I2[place]);

        moji = 'I';
        /*LL tmp = 0;
        for(int j=0; j<O.size(); j++){
            if(O[j] >= place){
                break;
            }
            tmp += J2[O[j]];
        }*/
        auto it = lower_bound(O.begin(), O.end(), place);
        if(it != O.begin()){
            it--;
            ans = max(ans, sum.back() + J3[ *it ]);
        }
        
    }

    cout << ans << endl;

    return 0;
}
accuracy: 1
time_ms: 490
memory_kb: 8952
final_rank: 16

code_snippet: #include <stdio.h>
typedef long long ll;

int main(void) {
  ll i, j, k, n, num = 0, ans, t1 = 0, t2 = 0;
  scanf("%lld", &n);
  char s[n +10];
  ll dp[n][3], sum[n][3];
  for(i = 0; i < n; ++i) for(j = 0; j < 3; ++j) dp[i][j] = 0, sum[i][j] = 0;
  scanf("%s", s);
  if(s[0] == 'J') sum[0][0] = 1;
  else if(s[0] == 'O') sum[0][1] = 1;
  else sum[0][2] = 1;
  for(i = 1; i < n; ++i) {
    for(j = 0; j < 3; ++j) sum[i][j] = sum[i - 1][j];
    if(s[i] == 'J') ++sum[i][0];
    else if(s[i] == 'O') ++sum[i][1];
    else ++sum[i][2];
  }
  if(s[0] == 'O') t1 = sum[n - 1][2] - sum[0][2];
  for(i = 1; i < n; ++i) if(s[i] == 'O') num += sum[i - 1][0] * (sum[n - 1][2] - sum[i][2]), t1 += (sum[i - 1][0] + 1) * (sum[n - 1][2] - sum[i][2]), t2 += sum[i - 1][0] *(sum[n - 1][2] - sum[i][2] + 1);
  ans = (t1 > t2 ? t1 : t2);
  //printf("%lld %lld ", t1, t2);
  for(i = 0; i < n; ++i) if(ans < num + sum[i][0] * (sum[n - 1][2] - sum[i][2])) {
    ans = num + sum[i][0] * (sum[n - 1][2] - sum[i][2]);
    //printf("%lld\n", i);
  }
  printf("%lld\n", ans);
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 7496
final_rank: 9

code_snippet: #include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int ch(string s){
  int dp[4][s.size()+1],ans=0;
  memset(dp,0,sizeof(dp));
  dp[0][0]=1;
  s="+"+s;
  string t="+JOI";
  for(int i=1;i<4;i++){
    for(int j=1,x=0;j<s.size();j++){
      x+=dp[i-1][j-1];
      if(s[j]==t[i]){
        dp[i][j]=x;
        if(i==3)ans+=dp[i][j];
      }
    }
  }
  return ans;
}
int ch2(string s){
  int ans=0;
  s="@"+s+"@";
  for(int i=1;i<(int)s.size();i+=2)s.insert(s.begin()+i,'O');
  int dp1[s.size()]={};
  int dp2[s.size()]={};
  for(int i=1;i<s.size();i++)dp1[i]=dp1[i-1]+(s[i-1]=='J');
  for(int i=s.size()-2;i>=0;i--)dp2[i]=dp2[i+1]+(s[i+1]=='I');
  for(int i=0;i<s.size();i++)ans=max(ans,dp1[i]*dp2[i]);
  return ans;
}
main(){
  string s;
  cin>>n>>s;
  int p1=ch(s);
  int p2=ch("J"+s);
  int p3=ch(s+"I");
  int p4=p1+ch2(s);
  cout<<max(p4,max(p3,p2))<<endl;
}
accuracy: 1
time_ms: 130
memory_kb: 6644
final_rank: 12

code_snippet: #include<iostream>
#include<algorithm>

using namespace std;
typedef long long ll;

ll N, ruisekiwa[100001][3];
char in[100000];

int main() {
	cin >> N;
	for (int i = 0; i < N; i++) {
		char c;
		cin >> c;
		if (c == 'J')ruisekiwa[i + 1][0]++;
		if (c == 'O')ruisekiwa[i + 1][1]++;
		if (c == 'I')ruisekiwa[i + 1][2]++;
		for (int j = 0; j < 3; j++)ruisekiwa[i + 1][j] += ruisekiwa[i][j];
		in[i] = c;
	}

	ll hajime = 0;
	for (int i = 0; i < N - 1; i++) {
		if (in[i] == 'O') {
			hajime += ((ruisekiwa[i + 1][0] - ruisekiwa[0][0]) * (ruisekiwa[N][2] - ruisekiwa[i + 1][2]));
		}
	}
	ll ans = hajime, tmp = 0;
	//J????????? ????????????????????????????????????
	for (int i = 0; i < N; i++) {
		if (in[i] == 'O') {
			tmp += ((ruisekiwa[i + 1][0] - ruisekiwa[0][0] + 1) * (ruisekiwa[N][2] - ruisekiwa[i + 1][2]));
		}
	}
	ans = max(ans, tmp), tmp = 0;

	//O????????? ??¨????????????

	for (int i = 0; i < N - 1; i++) {
		tmp = max(tmp, 
			(ruisekiwa[i + 1][0] - ruisekiwa[0][0]) * (ruisekiwa[N][2] - ruisekiwa[i + 1][2]));
	}
	ans = max(ans, hajime + tmp), tmp = 0;

	//I????????????????????????????????????????????????
	for (int i = 0; i < N; i++) {
		if (in[i] == 'O') {
			tmp += ((ruisekiwa[i + 1][0] - ruisekiwa[0][0]) * (ruisekiwa[N][2] - ruisekiwa[i + 1][2] + 1));
		}
	}
	ans = max(ans, tmp), tmp = 0;
	
	cout << ans << endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 5520
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using LL = long long;
using VL = vector<LL>;
using VVL = vector<VL>;
using PLL = pair<LL, LL>;
using VS = vector<string>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

#define FF first
#define SS second
template<class S, class T>
istream& operator>>(istream& is, pair<S,T>& p){
  return is >> p.FF >> p.SS;
}
template<class S, class T>
ostream& operator<<(ostream& os, const pair<S,T>& p){
  return os << p.FF << " " << p.SS;
}
template<class T>
void maxi(T& x, T y){
  if(x < y) x = y;
}
template<class T>
void mini(T& x, T y){
  if(x > y) x = y;
}


const double EPS = 1e-10;
const double PI  = acos(-1.0);
const LL MOD = 1e9+7;

string JOI = "JOI";
LL calc(string& S){
  int N = SZ(S);
  VVL cnt(N+1, VL(3));
  REP(i,N){
	REP(j,3)
	  cnt[i+1][j] = cnt[i][j] + (JOI[j] == S[i]);
  }

  LL res = 0;
  REP(i,N){
	if(S[i] == 'O'){
	  res += cnt[i][0] * (cnt[N][2] - cnt[i][2]);
	}
  }
  return res;
}

int main(){
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int N;
  cin >> N;
  string S;
  cin >> S;

  string J = "J" + S;
  string I = S + "I";

  LL ans = max(calc(J), calc(I));

  VVL cnt(N+1, VL(3));
  REP(i,N){
	REP(j,3)
	  cnt[i+1][j] = cnt[i][j] + (JOI[j] == S[i]);
  }
  LL orig = calc(S);
  REP(i,N)
	maxi(ans, orig + cnt[i][0] * (cnt[N][2] - cnt[i][2]));
  cout << ans << endl;

  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 14096
final_rank: 13

code_snippet: #include <iostream>
#include <algorithm>

using ll=long long int;

constexpr int MAX_N=100000;

int n;
int street[MAX_N];

int sum;

int main() {
	std::cin>>n;
	char ch;
	for(int i=0;i<n;++i){
		std::cin>>ch;
		if(ch=='O'){
			street[i]=1;
		}
		else if(ch=='I'){
			street[i]=2;
			++sum;
		}
	}
	ll base=0;
	int count=0,count1=0;
	for(int i=0;i<n;++i){
		if(!street[i])
			++count;
		else if(street[i]==1){
			base+=count*(sum-count1);
		}
		else if(street[i]==2)
			++count1;
	}
	ll ans=0;

	count=0;

	for(int i=0;i<n;++i){
		if(!street[i])
			++count;
		else if(street[i]==1)
			ans+=count;
	}

	count=0;
	ll tmp=0;

	for(int i=n-1;i>=0;--i){
		if(street[i]==2)
			++count;
		else if(street[i]==1)
			tmp+=count;
	}


	ans=std::max(ans,tmp);

	tmp=0;
	count=0;
	count1=0;

	for(int i=0;i<n;++i){
		if(!street[i])
			++count;
		else if(street[i]==2)
			++count1;
		ans=std::max(ans,(ll)count*(sum-count1));
	}

	std::cout<<ans+base<<std::endl;

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3480
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
int n;string T;vector<int>v;
long long search(string S){
	v.clear();
	for(int i=0;i<(int)S.size();i++){
		if(S[i]=='J')v.push_back(0);
		if(S[i]=='O')v.push_back(1);
		if(S[i]=='I')v.push_back(2);
	}
	vector<vector<long long> >dp(v.size()+1,vector<long long>(4,0));
	dp[0][0]=1;
	for(int i=0;i<(int)v.size();i++){
		dp[i+1][v[i]+1]+=dp[i][v[i]];
		for(int j=0;j<4;j++)dp[i+1][j]+=dp[i][j];
	}
	return dp[v.size()][3];
}
int main(){
	cin>>n>>T;long long ret=0;
	ret=max(ret,max(search("J"+T),search(T+"I")));
	long long c1=0,c2=0,w=search(T);
	for(int i=0;i<(int)T.size();i++){if(T[i]=='I')c2++;}
	for(int i=0;i<(int)T.size();i++){
		if(T[i]=='J')c1++;if(T[i]=='I')c2--;
		ret=max(ret,w+c1*c2);
	}
	cout<<ret<<endl;
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 10688
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
int n;string T;vector<int>v;
long long search(string S){
	v.clear();
	for(int i=0;i<(int)S.size();i++){
		if(S[i]=='J')v.push_back(0);
		if(S[i]=='O')v.push_back(1);
		if(S[i]=='I')v.push_back(2);
	}
	vector<vector<int> >dp(v.size()+1,vector<int>(4,0));
	dp[0][0]=1;
	for(int i=0;i<(int)v.size();i++){
		dp[i+1][v[i]+1]+=dp[i][v[i]];
		for(int j=0;j<4;j++)dp[i+1][j]+=dp[i][j];
	}
	return dp[v.size()][3];
}
int main(){
	cin>>n>>T;long long ret=0;
	ret=max(ret,max(search("J"+T),search(T+"I")));
	long long c1=0,c2=0,w=search(T);
	for(int i=0;i<T.size();i++){if(T[i]=='I')c2++;}
	for(int i=0;i<T.size();i++){
		if(T[i]=='J')c1++;if(T[i]=='I')c2--;
		ret=max(ret,w+c1*c2);
	}
	cout<<ret<<endl;
	return 0;
}
accuracy: 0.6666666666666666
time_ms: 10
memory_kb: 8992
final_rank: 17

code_snippet: #include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
class shop {
public:
	char stamp;
	ll num[3];
	ll dummy;
	shop():dummy(-1) {

	}
};

int main() {
	int time;
	cin >> time;
	shop *streat;
	streat = new shop[time + 1];
	for (int i = 0; i < 3; ++i) {
		streat[0].num[i] = 0;
	}
	char dummy;
	for (int i = 1; i <= time; ++i) {
		cin >> dummy;
		for (int j = 0; j < 3; ++j) {
			streat[i].num[j] = streat[i-1].num[j];
		}
		if (dummy == 'J') {
			++streat[i].num[0];
		}
		else if (dummy == 'O') {
			++streat[i].num[1];
		}
		else {
			++streat[i].num[2];
		}
		streat[i].stamp = dummy;
	}
	ll origin = 0;
	ll date;
	for (int i = time - 2; i >= 1; --i) {
		if (streat[i].stamp == 'J') {
			date = 0;
			for (int j = i + 1; j <= time; ++j) {
				if (streat[j].dummy != -1) {
					date += streat[j].dummy;
					break;
				}
				if (streat[j].stamp == 'O') {
					date += streat[time].num[2] - streat[j].num[2];
				}
			}
			streat[i].dummy = date;
			origin += date;
		}
	}
	date = 0;
	for (int j = 1; j <= time; ++j) {
		if (streat[j].stamp == 'O') {
			date += streat[time].num[2] - streat[j].num[2];
		}
	}
	ll answer = date;
	date = 0;
	for (int j = time; j >= 1; --j) {
		if (streat[j].stamp == 'O') {
			date += streat[j].num[0];
		}
	}
	answer = max(answer, date);
	for (int i = 2; i < time; ++i) {
		answer = max(answer, streat[i].num[0] * (streat[time].num[2] - streat[i].num[2]));
	}
	cout << origin + answer<< endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 7000
final_rank: 7

code_snippet: #include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
typedef double db;

#define fr first
#define sc second
#define pb push_back
#define rep(i,x) for(ll i=0;i<x;i++)
#define rep1(i,x) for(ll i=1;i<=x;i++)
#define rrep(i,x) for(ll i=x-1;i>=0;i--)
#define rrep1(i,x) for(ll i=x;i>0;i--)

string s;
ll N;
ll J[100000],O[100000],I[100000];
ll rJ[100000],rO[100000],rI[100000];
ll ans=0;
ll OI,JO;
int main()
{
	cin>>N;
	cin>>s;
	rep(i,N){
		if(s[i]=='J'){
			J[i]++;
			rJ[i]++;
		}
		else if(s[i]=='O'){
			O[i]++;
			rO[i]++;
		}
		else {
			I[i]++;
			rI[i]++;
		}
	}
	rep(i,N-1){
		J[i+1]+=J[i];
		O[i+1]+=O[i];
		I[i+1]+=I[i];
	}
	rrep(i,N-1){
		rJ[i]+=rJ[i+1];
		rO[i]+=rO[i+1];
		rI[i]+=rI[i+1];
	}
	ll cnt=0;
	rep(i,N){
		if(s[i]=='O'){
			ans+=J[i]*rI[i];
			OI+=rI[i];
			JO+=J[i];
		}
		cnt=max(cnt,J[i]*rI[i]);
	}
	cout<<ans+max(cnt,max(JO,OI))<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 8000
final_rank: 10

code_snippet: #include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <iterator>

using namespace std;

long long int const LL_MAX = 10000000000000000; // 10^16

long long int DP[3][100001];

long long int total(int N, string str){
	
	DP[0][0] = 0;
	DP[1][0] = 0;
	DP[2][0] = 0;
	
	str = " " + str;
	
	for(int i = 1; i <= N; i++){
		if(str[i] == 'J'){
			DP[0][i] = DP[0][i - 1] + 1;
		}else{
			DP[0][i] = DP[0][i - 1];
		}
	}
	for(int i = 1; i <= N; i++){
		if(str[i] == 'O'){
			DP[1][i] = DP[1][i - 1] + DP[0][i - 1];
		}else{
			DP[1][i] = DP[1][i - 1];
		}
	}
	for(int i = 1; i <= N; i++){
		if(str[i] == 'I'){
			DP[2][i] = DP[2][i - 1] + DP[1][i - 1];
		}else{
			DP[2][i] = DP[2][i - 1];
		}
	}
	return DP[2][N];
}

int main(){
	
	string str;
	int N;
	
	cin >> N;
	cin >> str;
	
	string str1, str3;
	
	str1 = "J" + str;
	str3 = str + "I";
	
	long long int I_sum = 0;
	
	for(int i = 0; i < N; i++){
		if(str[i] == 'I'){
			I_sum++;
		}
	}
	
	long long int J_count = 0;
	long long int O_max = 0;
	
	for(int i = 0; i < N; i++){
		if(str[i] == 'J'){
			J_count++;
		}else if(str[i] == 'I'){
			I_sum--;
		}
		if(J_count * I_sum > O_max){
			O_max = J_count * I_sum;
		}
	}
	
	long long int ans = max(max(total(N + 1, str1), total(N + 1, str3)), total(N, str) + O_max);
	
	cout << ans << endl;
	
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 6024
final_rank: 6

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <functional>

using namespace std;

#define int long long

#define fst first
#define scd second
#define PB push_back
#define MP make_pair
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define omajinai ios::sync_with_stdio(false);cin.tie(0)
#define rep(i,x) for(int i=0;i<(int)(x);++i)
#define rep1(i,x) for(int i=1;i<=(int)(x);++i)

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> pii;
typedef vector<pii> vpii;

template<typename T>T& max(T&a,T&b){if(a>=b)return a;return b;}
template<typename T>T& min(T&a,T&b){if(a<b)return a;return b;}
template<typename T>bool chmax(T&a,T b){if(a<b){a=b;return true;}return false;}
template<typename T>bool chmin(T&a,T b){if(a>b){a=b;return true;}return false;}
template<typename T>T get(){T a;cin>>a;return a;}
template<typename T>T rev(T a){reverse(all(a));return a;}
template<typename T>vector<T>&sort(vector<T>&a){sort(all(a));return a;}

const int inf = 1e9;
const ll linf = 3e18;
const double eps = 1e-9;

char S[100010];

int imosJ[100010];
int imosO[100010];
int imosI[100010];

int rev_imosJ[100010];
int rev_imosO[100010];
int rev_imosI[100010];

signed main()
{ // #define int long long ?????????????????§scanf???????????¨???????????????????????\?????????????????????
    int N; cin >> N;

    rep(i, N) cin >> S[i];

    int ma = 0;

    { // 'J'
        imosJ[0] += 1;

        rep1(i, N) imosJ[i] += imosJ[i - 1] + (S[i - 1] == 'J');
        rep1(i, N) imosO[i] += imosO[i - 1] + imosJ[i - 1] * (S[i - 1] == 'O'); // "JO" ?????°
        rep1(i, N) imosI[i] += imosI[i - 1] + imosO[i - 1] * (S[i - 1] == 'I'); // "JOI" ?????°

        ma = max(ma, imosI[N]);
    }

    { // 'I'
        memset(imosJ, 0, sizeof(imosJ));
        memset(imosO, 0, sizeof(imosO));
        memset(imosI, 0, sizeof(imosI));

        imosI[N] += 1;

        for (int i = N - 1; i >= 0; --i) imosI[i] += imosI[i + 1] + (S[i] == 'I');
        for (int i = N - 1; i >= 0; --i) imosO[i] += imosO[i + 1] + imosI[i + 1] * (S[i] == 'O');
        for (int i = N - 1; i >= 0; --i) imosJ[i] += imosJ[i + 1] + imosO[i + 1] * (S[i] == 'J');

        ma = max(ma, imosJ[0]);
    }

    { // 'O'
        memset(imosJ, 0, sizeof(imosJ));
        memset(imosO, 0, sizeof(imosO));
        memset(imosI, 0, sizeof(imosI));
        
        rep1(i, N) imosJ[i] += imosJ[i - 1] + (S[i - 1] == 'J');
        rep1(i, N) imosO[i] += imosO[i - 1] + imosJ[i - 1] * (S[i - 1] == 'O'); // "JO" ?????°
        rep1(i, N) imosI[i] += imosI[i - 1] + imosO[i - 1] * (S[i - 1] == 'I'); // "JOI" ?????°

        int sum = imosI[N];

        for (int i = N - 1; i >= 0; --i) rev_imosI[i] += rev_imosI[i + 1] + (S[i] == 'I');
        for (int i = N - 1; i >= 0; --i) rev_imosO[i] += rev_imosO[i + 1] + rev_imosI[i + 1] * (S[i] == 'O');
        for (int i = N - 1; i >= 0; --i) rev_imosJ[i] += rev_imosJ[i + 1] + rev_imosO[i + 1] * (S[i] == 'J');

        rep(i, N) {
            ma = max(ma, sum + imosJ[i + 1] * rev_imosI[i]);
        }
    }

    cout << ma << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 5948
final_rank: 5

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
using namespace std;
long long dp[110000][4], n; string T; char F[5] = "JOI!";
long long solve(string S) {
	for (int i = 0; i < 440000; i++)dp[i / 4][i % 4] = 0; dp[0][0] = 1;
	for (int i = 0; i < S.size(); i++) {
		for (int j = 0; j < 4; j++) {
			if (F[j] == S[i])dp[i + 1][j + 1] += dp[i][j];
			dp[i + 1][j] += dp[i][j];
		}
	}
	return dp[S.size()][3];
}
int main() {
	cin >> n >> T;
	long long J = 0, I = 0; for (int i = 0; i < T.size(); i++)if (T[i] == 'I')I++;
	int maxn = 0, maxid = 0;
	for (int j = 0; j < T.size(); j++) {
		if (T[j] == 'J')J++; if (T[j] == 'I')I--;
		if (J*I > maxn) { maxn = J*I; maxid = j + 1; }
	}
	string T1 = 'J' + T, T2 = T + 'I', T3 = T.substr(0, maxid) + 'O' + T.substr(maxid, T.size() - maxid);
	cout << max(solve(T1), max(solve(T2), solve(T3))) << endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 7216
final_rank: 8