Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions Algorithm/DifferenceArray/atcoder/B07/B07.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// この問題では最大で `T = 500000`, `N = 500000` と非常に大きくなるため、**差分配列(いもす法)**+**累積和**を使って高速に処理する必要があります。

// ## ✅ Goによる回答コード(標準入力 & 高速出力対応)
package main

import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)

func main() {
reader := bufio.NewReaderSize(os.Stdin, 1<<20) // 1MB buffer
scanner := bufio.NewScanner(reader)
scanner.Split(bufio.ScanLines)

// Helper function to read one line and convert to int
// readInt := func() int {
// scanner.Scan()
// val, _ := strconv.Atoi(scanner.Text())
// return val
// }

// First line: T (閉店時刻)
scanner.Scan()
T, _ := strconv.Atoi(scanner.Text())

// Second line: N (従業員数)
scanner.Scan()
N, _ := strconv.Atoi(scanner.Text())

// 差分配列の初期化
cnt := make([]int, T+1)

// 各従業員の[L, R)を読み取り、差分配列に記録
for i := 0; i < N; i++ {
scanner.Scan()
parts := strings.Fields(scanner.Text())
L, _ := strconv.Atoi(parts[0])
R, _ := strconv.Atoi(parts[1])
cnt[L] += 1
cnt[R] -= 1
}

// 出力用バッファ
writer := bufio.NewWriterSize(os.Stdout, 1<<20) // 1MB buffer
defer writer.Flush()

// 累積和をとって出力
current := 0
for t := 0; t < T; t++ {
current += cnt[t]
fmt.Fprintln(writer, current)
}
}

// ## 📥 入力形式(例)

// ```text
// 10
// 7
// 0 3
// 2 4
// 1 3
// 0 3
// 5 6
// 5 6
// 5 6
// ```

// ---

// ## 📤 出力形式

// ```text
// 2
// 3
// 4
// 1
// 0
// 3
// 0
// 0
// 0
// 0
// ```

// ---

// ## ✅ 説明

// ### データ構造

// | 変数名 | 型 | 内容 |
// | --------- | ------- | --------------- |
// | `T` | `int` | 営業時間(閉店時刻) |
// | `N` | `int` | 従業員数 |
// | `cnt` | `[]int` | 差分配列(サイズ `T+1`) |
// | `current` | `int` | 時刻 t にいる人数の累積値 |

// ---

// ## ⏱ パフォーマンス

// * 計算量:O(N + T)
// * メモリ:`cnt` 配列で最大 500001 要素 → 約 2MB
// * 入出力:`bufio.NewReaderSize`, `NewWriterSize` を使用して高速化

// ## ✅ 実行方法(ターミナル)

// ファイル名 `main.go` で保存して以下を実行:

// ```bash
// go run main.go < input.txt
// ```

// またはコンパイルして実行:

// ```bash
// go build main.go
// ./main < input.txt
// ```

84 changes: 84 additions & 0 deletions Algorithm/DifferenceArray/atcoder/B07/B07.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// この問題は、\*\*差分配列(いもす法)\*\*を使うことで高速に解けます。
// 各従業員が出勤する時に +1、退勤する時に -1 をして、累積和をとることで、
// **時刻 t+0.5 に店内にいる人数**を O(N+T) で計算できます。

// ---

// ### 🔧 アプローチ(いもす法)

// * `cnt[i]` を「時刻 `i + 0.5` に店内にいる人数」とすると、

// * 従業員 `(L, R)` がいたとき:

// * `cnt[L] += 1`
// * `cnt[R] -= 1`
// * 最後に累積和を取って `cnt[0]` ~ `cnt[T-1]` を出力。

// ### ✅ JavaScript (Node.js, `fs`使用)

const fs = require('fs');

const input = fs.readFileSync('/dev/stdin', 'utf8').trim().split('\n');
const T = parseInt(input[0], 10);
const N = parseInt(input[1], 10);

// 差分配列の初期化
const cnt = new Array(T + 1).fill(0);

// 各従業員の出退勤を処理
for (let i = 0; i < N; i++) {
const [L, R] = input[2 + i].split(' ').map(Number);
cnt[L] += 1;
cnt[R] -= 1;
}

// 累積和をとって出力
let current = 0;
for (let t = 0; t < T; t++) {
current += cnt[t];
console.log(current);
}

// ### 📈 実行時間とメモリ

// * 実行時間:O(N + T)
// * メモリ使用量:配列 `cnt` のサイズは最大 500,001 要素 → 約 4MB 以下

// ---

// ### 🧠 図による解説(例)

// 入力:

// ```
// T = 10, N = 3
// [L, R] = [0,3], [2,4], [1,3]
// ```

// 差分配列に追加:

// | 時刻 `t` | cnt\[t](差分) |
// | ------ | ----------- |
// | 0 | +1 |
// | 1 | +1 |
// | 2 | +1 |
// | 3 | -3 |
// | 4 | -1 |

// 累積和を取ると:

// | t | cnt (合計人数) |
// | --- | ---------- |
// | 0.5 | 1 |
// | 1.5 | 2 |
// | 2.5 | 3 |
// | 3.5 | 0 |
// | 4.5 | 0 |
// | ... | ... |

// ---

// ### ✅ 注意

// * 差分配列の添字は `[0, T]` まで必要(R == T の人に対応)
// * 出力は `console.log` を T 回実行して OK(T = 5e5 まで問題なし)
102 changes: 102 additions & 0 deletions Algorithm/DifferenceArray/atcoder/B07/B07.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<!-- この問題は最大で `T = 500000`, `N = 500000` と大きいため、**差分配列(いもす法)+ 累積和**を使って高速に処理します。

## ✅ PHPコード(型付き + 高速対応) -->

<?php

declare(strict_types=1);

/**
* メイン処理関数
*/
function main(): void {
$stdin = fopen('php://stdin', 'r');
if ($stdin === false) {
throw new RuntimeException("Failed to open stdin.");
}

/** @var int $T 営業終了時間 */
$T = (int)fgets($stdin);
/** @var int $N 従業員数 */
$N = (int)fgets($stdin);

/** @var array<int> $cnt 差分配列 */
$cnt = array_fill(0, $T + 1, 0);

// 差分配列への反映
for ($i = 0; $i < $N; $i++) {
$line = fgets($stdin);
if ($line === false) {
throw new RuntimeException("Failed to read line.");
}
[$L, $R] = array_map('intval', explode(' ', trim($line)));
$cnt[$L] += 1;
$cnt[$R] -= 1;
}

// 累積和と出力
$current = 0;
for ($t = 0; $t < $T; $t++) {
$current += $cnt[$t];
echo $current . "\n";
}

fclose($stdin);
}

main();

// ## 📥 入力例

// ```
// 10
// 7
// 0 3
// 2 4
// 1 3
// 0 3
// 5 6
// 5 6
// 5 6
// ```

// ## 📤 出力例

// ```
// 2
// 3
// 4
// 1
// 0
// 3
// 0
// 0
// 0
// 0
// ```

// ## 🧠 解説

// ### 主な変数と型

// | 変数名 | 型 | 内容 |
// | ---------- | ------------ | ------------- |
// | `$T` | `int` | 営業終了時刻(閉店時刻) |
// | `$N` | `int` | 従業員数 |
// | `$cnt` | `array<int>` | 差分配列(サイズ T+1) |
// | `$current` | `int` | 累積和で現在店内にいる人数 |
// | `$stdin` | `resource` | 標準入力リソース |

// ## 🧮 計算量

// * 差分更新:O(N)
// * 累積和:O(T)
// * 合計:**O(N + T)**(最大でも 1,000,000 程度)→ 制約内で余裕

// ## ✅ 実行方法

// ローカルでテストする場合:

// ```bash
// php main.php < input.txt
// ```
Loading