백준/문제풀이_python

18436 수열과 쿼리 37 python

휴대용치즈 2024. 2. 5. 02:27

https://www.acmicpc.net/problem/18436

 

18436번: 수열과 쿼리 37

길이가 N인 수열 A1, A2, ..., AN이 있다. 이때, 다음 쿼리를 수행하는 프로그램을 작성하시오. 1 i x: Ai를 x로 바꾼다. 2 l r: l ≤ i ≤ r에 속하는 모든 Ai중에서 짝수의 개수를 출력한다. 3 l r: l ≤ i ≤ r

www.acmicpc.net

 

 

 

문제 접근

세그먼트 트리문제

짝수와 홀수를 따로 저장해야할까 고민했는데, 저장할때 2로 나눠서 저장하면 한번에 계산된다는것을 파악했다.

0아니면 1로 저장을 한 다음 구간 합을 구한다.

구하려는 범위의 구간합은 홀수고 범위에서 구간합을 빼면 짝수가 나온다

 

 

 

코드

import sys
import math

input = sys.stdin.readline
"""
2243
%2했을 때
1의 개수가 홀수의 개수 
end-start+1에서 1개수 뺀게 짝수의 개수

"""

def init(start, end, index):
  if start != end:
    mid = (start + end) // 2
    tree[index] = init(start, mid, index*2) + init(mid+1, end, index*2+1)
  return tree[index]

def ans(targetStart, targetEnd, start, end, index):
  if targetStart>end or targetEnd<start:
    return 0
  if targetStart<=start and end<=targetEnd:
    return tree[index]
  mid = (start+end) // 2
  return ans(b, c, start, mid, index*2) + ans(b, c, mid+1, end, index*2+1)


def update(target, val):
  index = target + node - 1
  tree[index] = val%2
  while index>1:
    index//=2
    tree[index] = tree[index*2] + tree[index*2+1]
    

N = int(input())
node = 2**math.ceil(math.log2(N))
tree = [0] * (node*2+1)
tree[node:node+N] = list(map(int,input().split()))
for i in range(N):
  tree[node+i] %= 2
M = int(input())

init(1, node, 1)
for m in range(M):
  a,b,c = map(int,input().split())
  if a == 1:
    update(b, c)
  elif a == 2:
    print(c-b+1 - ans(b, c, 1, node, 1))
  else:
    print(ans(b, c, 1, node, 1))