Skip to content

Commit df2307d

Browse files
authored
Merge pull request #66 from myoshi2891/dev/macbook_pro
atcoder B08 - Counting Points 2次元累積和(2D prefix sum)
2 parents a2f401d + 8db504f commit df2307d

6 files changed

Lines changed: 750 additions & 0 deletions

File tree

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// 以下は、問題に対する **Go (Golang)** の解法です。
2+
// 制約(点数・クエリ最大10⁵、座標範囲1500)を踏まえ、**2次元累積和(2D prefix sum)** を使って高速にクエリ処理を行います。
3+
// 型を明示し、**実行時間とメモリ使用量を考慮**した設計です。
4+
5+
// ## ✅ 解法概要(再確認)
6+
7+
// * 入力された点を `grid[x][y]` にカウント。
8+
// * `prefix[x][y]` に (1,1)〜(x,y) の点数累積和を構築。
9+
// * 各クエリで矩形 `[a,c] × [b,d]` の点数を O(1) で取得。
10+
11+
// ## ✅ Go 実装(型明示・最適化済)
12+
13+
package main
14+
15+
import (
16+
"bufio"
17+
"fmt"
18+
"os"
19+
"strconv"
20+
"strings"
21+
)
22+
23+
const SIZE = 1501
24+
25+
func main() {
26+
reader := bufio.NewReaderSize(os.Stdin, 1<<20) // 1MB buffer
27+
writer := bufio.NewWriter(os.Stdout)
28+
defer writer.Flush()
29+
30+
// 数値の読み取り関数
31+
readInt := func() int {
32+
line, _ := reader.ReadString('\n')
33+
val, _ := strconv.Atoi(strings.TrimSpace(line))
34+
return val
35+
}
36+
37+
readInts := func() []int {
38+
line, _ := reader.ReadString('\n')
39+
fields := strings.Fields(line)
40+
res := make([]int, len(fields))
41+
for i, s := range fields {
42+
res[i], _ = strconv.Atoi(s)
43+
}
44+
return res
45+
}
46+
47+
// 点の数
48+
var N int = readInt()
49+
50+
// grid[x][y]: 各点のカウント
51+
var grid [SIZE][SIZE]int
52+
53+
for i := 0; i < N; i++ {
54+
p := readInts()
55+
x, y := p[0], p[1]
56+
grid[x][y]++
57+
}
58+
59+
// 2次元累積和の構築
60+
var prefix [SIZE][SIZE]int
61+
62+
for x := 1; x < SIZE; x++ {
63+
for y := 1; y < SIZE; y++ {
64+
prefix[x][y] = grid[x][y] +
65+
prefix[x-1][y] +
66+
prefix[x][y-1] -
67+
prefix[x-1][y-1]
68+
}
69+
}
70+
71+
// クエリ数
72+
var Q int = readInt()
73+
74+
for i := 0; i < Q; i++ {
75+
p := readInts()
76+
a, b, c, d := p[0], p[1], p[2], p[3]
77+
78+
count := prefix[c][d] -
79+
prefix[a-1][d] -
80+
prefix[c][b-1] +
81+
prefix[a-1][b-1]
82+
83+
fmt.Fprintln(writer, count)
84+
}
85+
}
86+
87+
// ## ✅ 実行例
88+
89+
// ### 入力
90+
91+
// ```
92+
// 5
93+
// 1 3
94+
// 2 5
95+
// 3 4
96+
// 2 6
97+
// 3 3
98+
// 3
99+
// 1 3 3 6
100+
// 1 5 2 6
101+
// 1 3 3 5
102+
// ```
103+
104+
// ### 出力
105+
106+
// ```
107+
// 5
108+
// 2
109+
// 4
110+
// ```
111+
112+
// ---
113+
114+
// ## ✅ 型と構造体の解説
115+
116+
// | 変数 | 型 | 説明 |
117+
// | ------------ | ----------------- | ------------- |
118+
// | `grid` | `[1501][1501]int` | 点の存在をカウント |
119+
// | `prefix` | `[1501][1501]int` | 2D累積和 |
120+
// | `readInt()` | `func() int` | 1行読み取り & 整数変換 |
121+
// | `readInts()` | `func() []int` | 複数整数を1行で読み取り |
122+
123+
// ---
124+
125+
// ## ✅ 計算量
126+
127+
// | 処理内容 | 時間計算量 |
128+
// | ------ | ------------ |
129+
// | グリッド構築 | O(N) |
130+
// | 累積和構築 | O(1500×1500) |
131+
// | クエリ処理 | O(Q) |
132+
// | **合計** | ≈ 数百万オーダー |
133+
134+
// → **Go の処理性能なら 5 秒以内で十分対応可能**
135+
136+
// ## ✅ メモリ消費量
137+
138+
// * `grid` + `prefix`: `1501×1501×4バイト×2 ≒ 約18MB`
139+
// * 制限(1024MiB)の **2%以下** に収まる。
140+
141+
// ## ✅ 補足
142+
143+
// * `bufio.Reader` を使って **高速な標準入力読み取り**。
144+
// * `fmt.Fprintln(writer, ...)` により、**高速な出力**を実現。
145+
// * 全体を **配列ベース(\[SIZE]\[SIZE]int)で確保済み**なので、メモリの再確保もなく非常に高速。
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// JavaScript(Node.js)で効率的にこの問題を解く実装です。\*\*2次元累積和(2D prefix sum)\*\*を使うことで、各クエリに対して **O(1)** で解答でき、全体で高速に処理できます。
2+
3+
// ### ✅ 解法概要(2次元累積和)
4+
// 1. **入力点をカウントしてグリッドにプロット**(最大1500×1500の2D配列)。
5+
// 2. **2次元累積和テーブル(prefixSum)を構築**。
6+
// 3. 各クエリごとに、**累積和を使って矩形領域内の点数を計算**。
7+
8+
// ### ✅ コード(`fs` 使用)
9+
const fs = require('fs');
10+
11+
const input = fs.readFileSync('/dev/stdin', 'utf8').trim().split('\n');
12+
let idx = 0;
13+
14+
// N: 点の数
15+
const N = parseInt(input[idx++]);
16+
const gridSize = 1501;
17+
18+
// グリッド初期化
19+
const grid = Array.from({ length: gridSize }, () => new Array(gridSize).fill(0));
20+
21+
// 点の入力
22+
for (let i = 0; i < N; i++) {
23+
const [x, y] = input[idx++].split(' ').map(Number);
24+
grid[x][y]++;
25+
}
26+
27+
// 2次元累積和を作成
28+
const prefixSum = Array.from({ length: gridSize }, () => new Array(gridSize).fill(0));
29+
30+
for (let x = 1; x < gridSize; x++) {
31+
for (let y = 1; y < gridSize; y++) {
32+
prefixSum[x][y] =
33+
grid[x][y] +
34+
prefixSum[x - 1][y] +
35+
prefixSum[x][y - 1] -
36+
prefixSum[x - 1][y - 1];
37+
}
38+
}
39+
40+
// Q: クエリ数
41+
const Q = parseInt(input[idx++]);
42+
43+
// クエリ処理
44+
const output = [];
45+
46+
for (let i = 0; i < Q; i++) {
47+
const [a, b, c, d] = input[idx++].split(' ').map(Number);
48+
49+
const result =
50+
prefixSum[c][d] -
51+
prefixSum[a - 1][d] -
52+
prefixSum[c][b - 1] +
53+
prefixSum[a - 1][b - 1];
54+
55+
output.push(result);
56+
}
57+
58+
// 結果出力
59+
console.log(output.join('\n'));
60+
// ### ✅ 実行時間とメモリ
61+
// * **実行時間**: 入力・累積和構築: `O(N + W * H)`、クエリ処理: `O(Q)`
62+
// * **空間使用**: `O(W * H)` = `O(1500 × 1500)` ≒ 約 9MB(安全)
63+
64+
// ### ✅ 入力例
65+
// ```bash
66+
// $ echo "5
67+
// 1 3
68+
// 2 5
69+
// 3 4
70+
// 2 6
71+
// 3 3
72+
// 3
73+
// 1 3 3 6
74+
// 1 5 2 6
75+
// 1 3 3 5" | node main.js
76+
// ```
77+
78+
// ```
79+
// 5
80+
// 2
81+
// 4
82+
// ```
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<!-- 以下は、指定された問題に対する **PHP による高速実装**です。
2+
入力制約(最大 100,000 点・クエリ、座標範囲 1〜1500)を考慮し、**2次元累積和(2D prefix sum)** を使って時間・メモリを最適化しています。
3+
4+
---
5+
6+
## ✅ 解法概要(再確認)
7+
8+
* 点の分布を `grid[x][y]` にカウント。
9+
* `prefix[x][y]` に左上から `(x, y)` までの点の個数の累積和を構築。
10+
* クエリに対し、**矩形和を O(1)** で計算。
11+
## ✅ PHP 実装(型明示 + 最適化)
12+
<?php
13+
14+
function readInts(): array {
15+
return array_map('intval', explode(' ', trim(fgets(STDIN))));
16+
}
17+
18+
function main(): void {
19+
$SIZE = 1501;
20+
21+
/** @var int $N */
22+
$N = intval(trim(fgets(STDIN)));
23+
24+
// 初期化: 点の存在を記録する2Dグリッド
25+
/** @var int[][] $grid */
26+
$grid = array_fill(0, $SIZE, array_fill(0, $SIZE, 0));
27+
28+
for ($i = 0; $i < $N; $i++) {
29+
[$x, $y] = readInts();
30+
$grid[$x][$y]++;
31+
}
32+
33+
// 累積和構築: prefix[x][y] は (1,1)〜(x,y) の矩形内の点数
34+
/** @var int[][] $prefix */
35+
$prefix = array_fill(0, $SIZE, array_fill(0, $SIZE, 0));
36+
37+
for ($x = 1; $x < $SIZE; $x++) {
38+
for ($y = 1; $y < $SIZE; $y++) {
39+
$prefix[$x][$y] = $grid[$x][$y]
40+
+ $prefix[$x - 1][$y]
41+
+ $prefix[$x][$y - 1]
42+
- $prefix[$x - 1][$y - 1];
43+
}
44+
}
45+
46+
// クエリ処理
47+
/** @var int $Q */
48+
$Q = intval(trim(fgets(STDIN)));
49+
50+
$output = [];
51+
52+
for ($i = 0; $i < $Q; $i++) {
53+
[$a, $b, $c, $d] = readInts();
54+
55+
$count = $prefix[$c][$d]
56+
- $prefix[$a - 1][$d]
57+
- $prefix[$c][$b - 1]
58+
+ $prefix[$a - 1][$b - 1];
59+
60+
$output[] = $count;
61+
}
62+
63+
echo implode("\n", $output) . "\n";
64+
}
65+
66+
main();
67+
68+
// ## ✅ 型解説(PHP 8.2対応)
69+
70+
// | 変数 | 型 | 説明 |
71+
// | --------- | --------- | ------- |
72+
// | `$N, $Q` | `int` | 点数、クエリ数 |
73+
// | `$grid` | `int[][]` | 点の数カウント |
74+
// | `$prefix` | `int[][]` | 2次元累積和 |
75+
// | `$output` | `int[]` | 各クエリの答え |
76+
77+
// ---
78+
79+
// ## ✅ 実行例(入力)
80+
81+
// ```bash
82+
// $ php main.php
83+
// ```
84+
85+
// ```
86+
// 5
87+
// 1 3
88+
// 2 5
89+
// 3 4
90+
// 2 6
91+
// 3 3
92+
// 3
93+
// 1 3 3 6
94+
// 1 5 2 6
95+
// 1 3 3 5
96+
// ```
97+
98+
// ### 出力
99+
100+
// ```
101+
// 5
102+
// 2
103+
// 4
104+
// ```
105+
106+
// ---
107+
108+
// ## ✅ 実行時間・メモリ分析
109+
110+
// ### 時間計算量
111+
112+
// | 処理 | 時間 |
113+
// | ------ | -------- |
114+
// | 入力 | O(N + Q) |
115+
// | グリッド構築 | O(N) |
116+
// | 累積和構築 | O(1500²) |
117+
// | クエリ処理 | O(Q) |
118+
119+
// → 合計 約 3百万ステップ程度。PHP でも余裕で **5秒以内**。
120+
121+
// ### メモリ使用量
122+
123+
// * `grid`, `prefix`: `1501 × 1501 × 4byte × 2 ≒ 約18MB`
124+
// * クエリ・結果出力等を含めても **30MB未満**
125+
// * 制限:1024 MiB 内に余裕で収まる
126+
127+
// ---
128+
129+
// ## ✅ 補足
130+
131+
// * `fgets(STDIN)` + `explode` を使って、**高速な入力処理**を実現。
132+
// * 2次元累積和の使い方は Python や TypeScript と同じです。
133+
134+
// ---
135+
136+
// ご希望であれば、**PHPでも2D累積和の図解やクエリ処理の可視化**も提供できます!必要ですか?

0 commit comments

Comments
 (0)