Problem:
勇者ビ太郎(Bitaro the Brave)

勇者のビ太郎は，魔王と対峙することとなった．

ビ太郎は，縦$H$ 行，横$W$ 列のマス目上に宝石(Jewel)，オーブ(Orb)，金塊(Ingot) を配置し，魔法を発動することによって魔王に攻撃をしようとしている．以下，マス目のうち上から$i$ 行目($1 \leq i \leq H$)，左から$j$ 列目($1 \leq j \leq W$) のマスを，マス($i, j$) と表す．

ビ太郎は今，それぞれのマスにこれら3 種類のうち1 個を配置した．今から魔法を発動しようとしているが，この魔法の威力はマス目上の宝石，オーブ，金塊の配置によって決まる．具体的には，次の条件を満たす整数($i, j, k, l$) ($1 \leq i < k \leq H, 1 \leq j < l \leq W$) の組の個数が，魔法の威力である．

条件：マス($i, j$) には宝石が，マス($i, l$) にはオーブが，マス($k, j$) には金塊が置かれている．

ビ太郎は，この魔法の威力が気になっている．

マス目上の宝石，オーブ，金塊の配置が与えられたとき，ビ太郎が発動する魔法の威力を求めるプログラムを作成せよ．

入力

入力は以下の形式で標準入力から与えられる．

$H$ $W$
$S_1$
:
$S_H$

$S_i$ ($1 \leq i \leq H$) は長さ$W$ の文字列で，その$j$ 文字目($1 \leq j \leq W$) がJ のときはマス($i, j$) に宝石が，O の ときはマス($i, j$) にオーブが，I のときはマス($i, j$) に金塊が置かれていることを表す．

出力

標準出力に，魔法の威力を表す整数を1 行で出力せよ．

制約

$2 \leq H \leq 3 000$．

$2 \leq W \leq 3 000$．

$S_i$ は長さ$W$ の文字列である($1 \leq i \leq H$)．

$S_i$ の各文字はJ，O，I のいずれかである($1 \leq i \leq H$)．

入出力例

入力例1

3 4
JOIJ
JIOO
IIII

出力例1

3

この入力例では，($i, j, k, l$) = (1, 1, 3, 2), (2, 1, 3, 3), (2, 1, 3, 4) の3 個の組が条件を満たすので，答えは3 である．

入力例2

4 4
JJOO
JJOO
IIJO
IIIJ

出力例2

17

情報オリンピック日本委員会作 『第18 回日本情報オリンピック(JOI 2018/2019) 本選』

Solution in Rust (judge verdict: Accepted)

use std::io::*;
fn read(s: &mut StdinLock, num: usize) -> Vec<usize> {
    let stdin_iter = &mut s.by_ref().bytes().map(|c| c.unwrap() as char);
    (0..num).map(|_| 
        stdin_iter
            .take_while(|c| !c.is_whitespace())
            .skip_while(|c| c.is_whitespace())
            .fold(0, |a, x| (x as u8 - b'0') as usize + a * 10)
    ).collect()
}

fn main() {
    let s = stdin();
    let mut s = s.lock();
    let hw: Vec<usize> = read(&mut s, 2);
    let h = hw[0];
    let w = hw[1];
    let squares: Vec<Vec<char>> = {
        let mut squares: Vec<Vec<char>> = Vec::new();
        for _ in 0..h {
            squares.push(
                s.by_ref().bytes().map(|c| c.unwrap() as char)
                    .take_while(|c| !c.is_whitespace())
                    .skip_while(|c| c.is_whitespace())
                    .collect::<Vec<char>>());
        }
        squares
    };
    let mut ans: u64 = 0;
    let mut h_cnts: Vec<u64> = vec![0; w];
    for i in (0..h).rev() {
        let mut o_cnt: u64 = 0;
        for j in (0..w).rev() {
            if squares[i][j] == 'I' {
                h_cnts[j] += 1;
            } else if squares[i][j] == 'O' {
                o_cnt += 1;
            } else {
                ans += h_cnts[j] * o_cnt;
            }
        }
    }
    println!("{}", ans);
}