[11505] 구간 곱 구하기 (세그먼트 트리)

2023. 6. 5. 17:39·Coding Test/Tree
728x90
 

11505번: 구간 곱 구하기

첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)과 M(1 ≤ M ≤ 10,000), K(1 ≤ K ≤ 10,000) 가 주어진다. M은 수의 변경이 일어나는 횟수이고, K는 구간의 곱을 구하는 횟수이다. 그리고 둘째 줄부터 N+1번째 줄

www.acmicpc.net

 

분석

 

세그먼트 트리, 인덱스 트리, 구간합

1. 세그먼트 트리 주어진 데이터의 구간합과 데이터 업데이트를 빠르게 수행하기 위해 고안해낸 자료구조 2. 구간합 합배열(prefix sum)은 업데이트가 느림 arr[1]를 update 한다면 ? sum[1]부터 sum[9]까지

karla.tistory.com

 

 

풀이

"""
어떤 N개의 수가 주어져 있다. 그런데 중간에 수의 변경이 빈번히 일어나고 그 중간에 어떤 부분의 곱을 구하려 한다.
1, 2, 3, 4, 5 라는 수가 있고, 3번째 수를 6으로 바꾸고 2번째부터 5번째까지 곱을 구하라고 한다면 240을 출력하면 되는 것이다.
그리고 그 상태에서 다섯 번째 수를 2로 바꾸고 3번째부터 5번째까지 곱을 구하라고 한다면 48이 될 것이다.
첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)과 M(1 ≤ M ≤ 10,000), K(1 ≤ K ≤ 10,000) 가 주어진다.
 M은 수의 변경이 일어나는 횟수이고, K는 구간의 곱을 구하는 횟수이다.
둘째 줄부터 N+1번째 줄까지 N개의 수가 주어진다.
N+2번째 줄부터 N+M+K+1 번째 줄까지 세 개의 정수 a,b,c가 주어지는데, a가 1인 경우 b번째 수를 c로 바꾸고 a가 2인 경우에는 b부터 c까지의 곱을 구하여 출력하면 된다.
입력으로 주어지는 모든 수는 0보다 크거나 같고, 1,000,000보다 작거나 같은 정수이다.
첫째 줄부터 K줄에 걸쳐 구한 구간의 곱을 1,000,000,007로 나눈 나머지를 출력한다.
"""
import sys
input = sys.stdin.readline

n,m,k=map(int, input().split())  # 수의개수, 변경횟수, 구간곱출력횟수
treeHeight=0  # 트리높이
length=n  # 리프노드개수
MOD=1000000007

while length!=0:
    length//=2
    treeHeight+=1

treeSize=pow(2,treeHeight+1)  # 트리길이
leftStartIdx=treeSize//2-1  # 리프노드 전 인덱스
tree = [1]*(treeSize+1)  # 인덱스 트리 저장 리스트

# 데이터를 리프노드에 저장
for i in range(leftStartIdx+1, leftStartIdx+n+1):
    tree[i] = int(input())

# 인덱스 트리 생성 함수
def setTree(idx):
    while idx!=1:  # 인덱스가 루트노드가 아닐때까지
        tree[idx//2]=tree[idx]*tree[idx//2]%MOD
        idx-=1

setTree(treeSize-1)  # 2ᵏ-1부터 2까지
# print(tree)

# 값 변경 함수
def changeVal(idx, val):
    tree[idx]=val
    while idx>1:
        idx=idx//2
        tree[idx]=tree[idx*2]%MOD*tree[idx*2+1]%MOD

# 구간곱 출력 함수
def getMul(sIdx, eIdx):
    mul = 1
    while sIdx <= eIdx:
        if sIdx%2==1:  # 선택 : 부모노드 대상범위 제거, 독립노드
            mul=mul*tree[sIdx]%MOD
            sIdx+=1
        sIdx=sIdx//2
        if eIdx%2==0:  # 선택 : 부모노드 대상범위 제거, 독립노드
            mul=mul*tree[eIdx]%MOD
            eIdx-=1
        eIdx=eIdx//2
    return mul

for _ in range(m+k):
    q,s,e = map(int, input().split())
    if q == 1:  # 변경
        changeVal(leftStartIdx+s, e)
    elif q == 2:  # 출력
        b = leftStartIdx+s
        c = leftStartIdx+e
        print(getMul(b, c))

 

 

 

 

728x90
저작자표시 비영리 변경금지 (새창열림)
'Coding Test/Tree' 카테고리의 다른 글
  • [14425] 문자열 집합 (트라이, Trie)
  • [10868] 최솟값 (세그먼트 트리)
  • [11437] 최소 공통 조상 (트리, 일반 LCA)
  • [1068] 트리 (리프 노드의 개수 구하기, DFS)
Karla Ko
Karla Ko
𝘾𝙤𝙣𝙩𝙞𝙣𝙪𝙤𝙪𝙨𝙡𝙮 𝙄𝙢𝙥𝙧𝙤𝙫𝙞𝙣𝙜, 𝘾𝙤𝙣𝙨𝙩𝙖𝙣𝙩𝙡𝙮 𝘿𝙚𝙫𝙚𝙡𝙤𝙥𝙞𝙣𝙜 𝙔𝙚𝙨!
    250x250
  • Karla Ko
    karlaLog
    Karla Ko
  • 전체
    오늘
    어제
    • Total (461)
      • AI (1)
      • Infra (13)
        • Architecture (2)
        • Kubernetes (5)
        • Docker (3)
        • Cloud (1)
        • DevOps (1)
        • Monitoring (1)
      • Message Queue (4)
        • Kafka (2)
        • RabbitMQ (2)
      • Spring (19)
      • JPA (4)
      • Language (9)
        • Kotlin (1)
        • Java (8)
      • Git (4)
      • DB (4)
      • CS (11)
        • OS (8)
        • Network (2)
        • Algorithm (1)
      • Coding Test (392)
        • programmers (156)
        • Graph (43)
        • DP (37)
        • Search (31)
        • Tree (13)
        • Data Structure (26)
        • Combination (12)
        • Implement (18)
        • Geedy (23)
        • Sort (7)
        • Math (21)
        • geometry (2)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    다익스트라
    구현
    스택
    Algorithm
    그래프
    조합
    파이썬
    BFS
    최단거리
    구간합
    재귀
    LIS
    월간코드챌린지
    동적계획법
    DP
    그리디
    알고리즘
    백준
    큐
    덱
    트리
    최대공약수
    힙
    DFS
    정렬
    최소신장트리
    이분탐색
    프로그래머스
    자료구조
    플로이드워셜
  • hELLO· Designed By정상우.v4.10.3
Karla Ko
[11505] 구간 곱 구하기 (세그먼트 트리)
상단으로

티스토리툴바