AOJ 0560 - Planetary Exploration

久しぶりに番兵法を用いました.
方針はdp[y][x][t]を(y, x')( 1 \leq x' \leq x)で地形がtとなる個数とします.
すると,(x1, y) (x2, y)間( x1 \leq x2)の地形tの個数はdp[y][x2] - dp[y][x1-1]となります.((1, 1)起点なので負になりません.嬉しいですね)
(x1, y1) (x2, y2)間ではyを変えながら足していけば終わりです.
計算量はO(WH)でしょう.

#include<iostream>

int H, W, K;
int dp[1001][1001][3];

int solve(int x1, int y1, int x2, int y2, int type){
	int res = 0;
	for(int y=y1;y<=y2;y++){
		res += dp[y][x2][type] - dp[y][x1-1][type];
	}
	return res;
}

int main(){
	std::cin >> H >> W >> K;
	for(int y=1;y<=H;y++){
		for(int x=1;x<=W;x++){
			char c;
			std::cin >> c;
			if(c == 'J')dp[y][x][0]++;
			if(c == 'O')dp[y][x][1]++;
			if(c == 'I')dp[y][x][2]++;
			for(int i=0;i<3;i++){
				dp[y][x][i] += dp[y][x-1][i];
			}
		}
	}

	while(K--){
		int x1, y1, x2, y2;
		std::cin >> y1 >> x1 >> y2 >> x2;
		std::cout << solve(x1, y1, x2, y2, 0);
		for(int t=1;t<3;t++){
			std::cout << " " << solve(x1, y1, x2, y2, t);
		}
		std::cout << "\n";
	}
}