1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【競技プログラミング】AtCoder Beginner Contest 403

Last updated at Posted at 2025-09-08

既存投稿一覧ページへのリンク

一覧ページ

Before

AtCoder Beginner Contest 402

Next

AtCoder Beginner Contest 404

雑記

解けそうな問題は積極的にWAを出して、どのようなテストケースのときにエラーが出るか検証する方針で進めて見ようかな。
AtCoderの問題は、勉強のやり方を試行錯誤していて、どの方式でやっても壁にぶつかってしまい、結局は一番最初にやって、面倒くさくてやめた勉強法が一番良いという結論に至りつつある・・・

C問題

入力例01

input

2 3 5
1 1 2
3 1 1
3 1 2
2 2
3 2 3

input_python

input.py
def io_func():
    # 最初の1行目を取得し、n, m, qを整数として取得
    n, m, q = map(int, input().split())
    queries = []
    # q回分の入力行をリストとして取得
    for _ in range(q):
        queries.append([int(x) for x in input().split()])
    # 変数をまとめて返す
    return n, m, q, queries

output

No
Yes
Yes

WA(ac->2, ac->25, wa -> 18)

時間の余裕ではなく、精神的な余裕があるときにWAとなるテストパターンを生成して検証してみることにしよう。
入力例はACしたものの、テストケースを出したらWA出現。
TLEはきついけど、WAはウェルカ~ム。

input.py
def io_func():
    # 最初の1行目を取得し、n, m, qを整数として取得
    n, m, q = map(int, input().split())
    queries = []
    # q回分の入力行をリストとして取得
    for _ in range(q):
        queries.append([int(x) for x in input().split()])
    # 変数をまとめて返す
    return n, m, q, queries

from sortedcontainers import SortedList
def solve(n, m, q, queries):
    sl = [SortedList() for _ in range(m+1)]
    for query in queries:
        if query[0] == 2:
            sl[m].add(query[1])
        elif query[0] == 1:
            sl[query[2]].add(query[1])
        else:
            if query[1] in sl[m]:
                print("Yes")
            elif query[1] in sl[query[2]]:
                print("Yes")
            else:
                print("No")

if __name__=="__main__":
    n, m, q, queries = io_func()
    solve(n, m, q, queries)

D問題

解法 ver.250906

整数列Aを昇順に整列し、二分探索かな・・・

入力例01

長さ 5 の整数列

$A = (3, 1, 4, 1, 5)$

と、非負整数 D = 2 が与えられます。

この整数列 A の要素をいくつか削除して、以下の条件を満たす数列 B を作りたいです。

  • すべての $1 \leq i < j \leq |B|$ について、 $|B_i - B_j| \neq 2$ である。

すなわち、作りたい数列 B の中では、どの 2 つの要素を比べても「差がちょうど 2」になるような組が存在してはいけません。

最小でいくつの要素を削除すればよいか求めてください。

input

5 2
3 1 4 1 5

input_python

input.py
def io_func():
    # 標準入力からN, Dを整数として取得
    n, d = map(int, input().split())
    # 標準入力からリストAを整数リストとして取得
    a = list(map(int, input().split()))
    # 取得した値を戻り値として返す
    return n, d, a

output

1

入力例03

長さ 10 の整数列
$A = (1, 6, 2, 10, 2, 3, 2, 10, 6, 4)$
と、非負整数 D = 3 が与えられます。

この整数列 A の要素をいくつか削除して、以下の条件を満たす数列 B を作りたいです。

  • すべての $1 \leq i < j \leq |B|$ について、$|B_i - B_j| \neq 3$ である。

すなわち、作りたい数列 B の中では、どの 2 つの要素を比べても「差がちょうど 3」になるような組が存在してはいけません。

最小でいくつの要素を削除すればよいか求めてください。

input

10 3
1 6 2 10 2 3 2 10 6 4

output

2

E問題

入力例01

はじめ、文字列の多重集合 $X, Y$ はどちらも空です。
次の 4 個のクエリを順に処理してください。

  1. クエリ: 「1 at」

    • $T=1$ なので、文字列 "at" を多重集合 $X$ に追加する。
  2. クエリ: 「2 watcoder」

    • $T=2$ なので、文字列 "watcoder" を多重集合 $Y$ に追加する。
  3. クエリ: 「2 atcoder」

    • $T=2$ なので、文字列 "atcoder" を多重集合 $Y$ に追加する。
  4. クエリ: 「1 wa」

    • $T=1$ なので、文字列 "wa" を多重集合 $X$ に追加する。

各クエリの処理後に、次の値を出力してください:

  • 多重集合 $Y$ に含まれる文字列のうち、
    多重集合 $X$ のどの要素も接頭辞(prefix)として持たないものの個数。

  1. クエリ後: X = "at", Y = {}

    • $Y$ が空なので答えは 0
  2. クエリ後: X = { "at" }, Y = { "watcoder" }

    • "watcoder" の接頭辞は "w", "wa", "wat" ... などであり、$X$ の "at" は一致しない。
    • よって答えは 1
  3. クエリ後: X = { "at" }, Y = { "watcoder", "atcoder" }

    • "watcoder": 接頭辞に "at" は含まれない → OK
    • "atcoder": 接頭辞に "at" が含まれる → NG
    • よって答えは 1
  4. クエリ後: X = { "at", "wa" }, Y = { "watcoder", "atcoder" }

    • "watcoder": 接頭辞 "wa" が $X$ にあるので NG
    • "atcoder": 接頭辞 "at" が $X$ にあるので NG
    • よって答えは 0

input

4
1 at
2 watcoder
2 atcoder
1 wa

input_python

input.py
def io_func():
    # クエリ数を標準入力から取得
    n = int(input())
    # クエリ情報(タプルのリスト)の初期化
    q = []
    for _ in range(n):
        # 1行分を取得して、分割(タイプと文字列)
        ty, s = input().split()
        # クエリとしてタプルで追加
        q.append((ty, s))
    # すべてのクエリを戻り値として返す
    return q

output

0
1
1
0

WA(ac->2, ac->9, wa->3, tle->32, re->13) --- ver. 2025'09/09

正直、TLEするのは提出前にわかっていたけれど、waとかreとか出てくるのは想定外だった…
少し前までは、なんでACしねーんだよっ!って嘆いていたけれど、気持ちに余裕が出来た今、どういうケースでwaやreが起きるか発掘作業が楽しみになっているんだ。
tleは、まぁ当面放置しておこう。
今は効率の良いアルゴリズムより、効率が悪くてもACを取れるコードを思いつくようになることを優先にしたいんだ。

wa.py
class TrieNode:
    # Trie木の各ノードを表すクラス
    def __init__(self):
        # 子ノードを格納する辞書
        self.children = {}
        # このノードが単語の終端かどうかを記録
        self.is_end = False

class Trie:
    # Trie木全体を表すクラス
    def __init__(self):
        # 木構造の根ノードを初期化
        self.root = TrieNode()

    def insert(self, word):
        # 単語wordをTrieに挿入するメソッド
        node = self.root  # 根ノードから始める
        for char in word:
            # 各文字について、子ノードがなければ新規作成
            if char not in node.children:
                node.children[char] = TrieNode()
            # 子ノードに移動
            node = node.children[char]
        # 最後のノードを単語終端とする
        node.is_end = True

    def display(self, node=None, prefix=""):
        # Trieに格納された全ての単語を列挙するメソッド
        if node is None:
            node = self.root  # 初期は根ノード
        result = []
        # 単語の終端ならプレフィックスを結果に追加
        if node.is_end:
            result.append(prefix)
        # 全ての子ノードを再帰的に探索
        for char, child in node.children.items():
            result.extend(self.display(child, prefix + char))
        return result

    def count_prefix(self, prefix):
        # prefix(例: "ac")までノードを辿る
        node = self.root
        for char in prefix:
            if char not in node.children:
                return 0  # 該当する接頭辞がない場合
            node = node.children[char]
        # 以降のノードに格納された単語終端数を数える
        def dfs_count(n):
            c = 1 if n.is_end else 0
            for child in n.children.values():
                c += dfs_count(child)
            return c
        return dfs_count(node)


    def delete_prefix(self, prefix):
        node = self.root
        parent = None
        char_to_delete = None
        for char in prefix:
            if char not in node.children:
                return  # そのprefixの単語がない場合は何もしない
            parent = node
            char_to_delete = char
            node = node.children[char]
        # prefix直前の親ノードから、prefix部の子ノードを削除
        if parent and char_to_delete in parent.children:
            del parent.children[char_to_delete]

    def size(self):
        def dfs(node):
            count = 1 if node.is_end else 0
            for child in node.children.values():
                count += dfs(child)
            return count
        return dfs(self.root)


def io_func():
    # クエリ数を標準入力から取得
    n = int(input())
    # クエリ情報(タプルのリスト)の初期化
    q = []
    for _ in range(n):
        # 1行分を取得して、分割(タイプと文字列)
        ty, s = input().split()
        # クエリとしてタプルで追加
        q.append((int(ty), s))
    # すべてのクエリを戻り値として返す
    return q

def solve(q):
    trie = Trie()
    stack_counter = 0
    temp_ans = 0
    chk_list = []
    for v, query in q:
        if v==1:
            chk_list.append(query)
            chk_list = list(set(chk_list))
            for del_v in chk_list:
                trie.delete_prefix(del_v)
            ans = trie.size()
            print(ans)
        elif v==2:
            trie.insert(query)
            # v==1で追加したスタックの情報を削除する
            for del_v in chk_list:
                trie.delete_prefix(del_v)
            ans = trie.size()
            print(ans)


if __name__=="__main__":
    q = io_func()
    solve(q)

F問題

入力例01

以下は <expr> シンボルに従う有効な数式の例です。

  • 1111+111 : 1111 + 111 を表します。
  • (1+1)*(1+1) : (1+1) × (1+1) を表します。
  • (11+(1+1)*(1+1))+1 : (11+(1+1)×(1+1))+1 を表します。

一方、次の文字列は <expr> に従わないため不正です:

  • (1+1)(1+1)
  • 1+2
  • 1-1
  • 1/1
  • )1(
  • 1++1
  • +1
  • (+1)
  • 1*+1

9になる文字列のうち長さが最小のものを出力してください。

input

9

input_python

input.py
def io_func():
    n = int(input())   # 標準入力から整数Nを取得
    return n           # 整数Nを戻り値として返す

output

(1+1+1)*(1+1+1)
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?