公式

C - 魔法陣の反転 / Inversion of the Magic Square 解説 by admin

DeepSeek V3

Overview

This problem involves a mathematical expression written in Polish notation (prefix notation), where you need to find the evaluation results before and after flipping the operator at a specified position (+-, */).

Analysis

The basic method to evaluate a Polish notation expression is to process tokens from back to front using a stack. In this problem, we need to evaluate both the original expression and the expression with the flipped operator.

A straightforward approach is to independently evaluate both the original token sequence and the modified token sequence. Since each evaluation takes \(O(N)\) time with respect to the number of tokens \(N\), the total execution time is \(O(N)\). Given the constraint \(N \leq 2 \times 10^5\), this approach is sufficiently fast.

An important note: division / is integer division that truncates toward zero, which differs from Python’s standard integer division (//). In particular, special handling is needed to obtain correct results for divisions involving negative numbers.

Algorithm

  1. Read the token sequence and the flip position from the input
  2. Create a copy of the original token sequence and produce a modified token sequence with the operator at the specified position flipped
  3. Perform the following evaluation on both token sequences:
    • Process the token sequence from back to front
    • If the token is an operator, pop two values from the stack, compute the result, and push it onto the stack
    • If the token is an integer, push its value onto the stack
  4. Output the final result remaining on the stack

For the division operation, truncation toward zero is implemented as follows: - If the dividend and divisor have different signs, the result is negative - Perform division on absolute values, then adjust the sign

Complexity

  • Time complexity: \(O(N)\)
    • Copying the token sequence: \(O(N)\)
    • Flipping the operator: \(O(K)\)
    • Evaluation (2 times): \(O(N)\) each
  • Space complexity: \(O(N)\)
    • Storing the token sequence: \(O(N)\)
    • Evaluation stack: \(O(N)\)

Implementation Details

  • Division implementation: Standard integer division (//) truncates toward negative infinity, which differs from the truncation toward zero required by the problem. You need to manage signs separately and perform division on absolute values.

  • Token processing order: Since Polish notation is prefix notation, processing from back to front allows natural evaluation.

  • Flip position management: The position is given as \(1\)-indexed, so it needs to be converted to \(0\)-indexed.

  • Avoiding division by zero: The problem constraints guarantee that division by zero does not occur, but checks are included for safety.

    Source Code

import sys

def main():
    data = sys.stdin.read().splitlines()
    if not data:
        return
    
    n = int(data[0].strip())
    tokens = data[1].split()
    k = int(data[2].strip())
    flip_positions = set()
    if k > 0:
        flip_positions = set(map(int, data[3].split()))
    
    original_tokens = tokens.copy()
    flipped_tokens = tokens.copy()
    
    for pos in flip_positions:
        idx = pos - 1
        op = flipped_tokens[idx]
        if op == '+':
            flipped_tokens[idx] = '-'
        elif op == '-':
            flipped_tokens[idx] = '+'
        elif op == '*':
            flipped_tokens[idx] = '/'
        elif op == '/':
            flipped_tokens[idx] = '*'
    
    def evaluate(toks):
        stack = []
        for token in reversed(toks):
            if token in {'+', '-', '*', '/'}:
                a = stack.pop()
                b = stack.pop()
                if token == '+':
                    res = a + b
                elif token == '-':
                    res = a - b
                elif token == '*':
                    res = a * b
                elif token == '/':
                    if a == 0 or b == 0:
                        res = 0
                    else:
                        sign = 1
                        if (a < 0) != (b < 0):
                            sign = -1
                        res = sign * (abs(a) // abs(b))
                stack.append(res)
            else:
                stack.append(int(token))
        return stack[0]
    
    original_result = evaluate(original_tokens)
    flipped_result = evaluate(flipped_tokens)
    
    print(original_result)
    print(flipped_result)

if __name__ == "__main__":
    main()

This editorial was generated by deepseekv3.

投稿日時:
最終更新: