公式

A - カードバトル / Card Battle 解説 by admin

Gemini 3.1 Pro (Thinking)

Overview

\(N\) cards are laid out, and we sequentially perform operations where cards with adjacent numbers compare their attack power according to given conditions, and one absorbs (removes) the other. The problem asks for the number of cards remaining after all operations are completed.

Analysis

The most important point in this problem is that “the operation targets cards with numbers \(i\) and \(i+1\), not cards that are physically adjacent on the table.” When a card is removed, the remaining cards are not shifted to fill the gap — card numbers remain unchanged from start to finish. Therefore, at each step, we simply need to check “are both card \(i\) and card \(i+1\) still present?”

If we naively implement this by “deleting the element from the array (shifting elements left) when a card is removed,” the shifting operation takes \(O(N)\) time, resulting in an overall time complexity of \(O(N^2)\), which will cause a Time Limit Exceeded (TLE) with the maximum constraint of \(N=10^6\).

To solve this, we prepare a flag (marker) array that tracks “whether each card is currently still on the table.” This allows us to process each step in \(O(1)\) without physically deleting elements from the array.

Algorithm

  1. Manage the attack power of each card in an array \(A\).
  2. Prepare a boolean array alive indicating whether each card is still on the table, with all initial values set to True.
  3. For \(i = 1, 2, \ldots, N-1\) in order, perform the following operations (note that in the program, indices start from \(0\)):
    • Check whether both alive[i] and alive[i+1] are True.
    • If both are True, compare attack powers \(A_i\) and \(A_{i+1}\).
      • If \(A_i > A_{i+1}\): Add \(\lfloor A_{i+1} / 2 \rfloor\) to \(A_i\) and set alive[i+1] to False.
      • If \(A_i < A_{i+1}\): Add \(\lfloor A_i / 2 \rfloor\) to \(A_{i+1}\) and set alive[i] to False.
      • If the attack powers are equal, do nothing.
  4. Finally, count the number of True values in the alive array and output it.

Complexity

  • Time complexity: \(O(N)\)
    • We only loop through the array once to check and update adjacent elements, so the overall complexity is \(O(N)\). Even with \(N=10^6\), this comfortably fits within the time limit.
  • Space complexity: \(O(N)\)
    • We use \(O(N)\) memory for the array \(A\) storing attack powers and the array alive storing survival flags.

Implementation Notes

  • Floor division: The \(\lfloor Y / 2 \rfloor\) in the attack power update can be easily computed in Python using the // operator, which performs integer division with truncation toward negative infinity.

  • Fast I/O: Since \(N\) can be as large as \(10^6\), in Python it is safer and faster to read all input at once using sys.stdin.read().split().

  • 0-indexed: The problem statement numbers cards from \(1\) to \(N\), but in actual programming languages (such as Python), array indices start from \(0\), so the loop should be implemented from \(i = 0\) to \(N-2\).

    Source Code

import sys

def main():
    input = sys.stdin.read
    data = input().split()
    if not data:
        return
    N = int(data[0])
    A = [int(x) for x in data[1:]]
    
    alive = [True] * N
    for i in range(N - 1):
        if alive[i] and alive[i + 1]:
            if A[i] > A[i + 1]:
                A[i] += A[i + 1] // 2
                alive[i + 1] = False
            elif A[i] < A[i + 1]:
                A[i + 1] += A[i] // 2
                alive[i] = False

    print(sum(alive))

if __name__ == '__main__':
    main()

This editorial was generated by gemini-3.1-pro-thinking.

投稿日時:
最終更新: