1. paizaラーニングトップ
  2. レベルアップ問題集
  3. Binary Indexed Treeメニュー(言語選択)
  4. 問題一覧 Python3編
  5. BITの区間総和 1 : インデックス計算 Python3編

Binary Indexed Treeメニューのサムネイル
BITの区間総和 1 : インデックス計算 Python3編(paizaランク B 相当)

問題にチャレンジして、ユーザー同士で解答を教え合ったり、コードを公開してみよう!

問題

下記の問題をプログラミングしてみよう!

(はじめに)



問題 4,5 にてBITの一点加算を行ってきました。

最後にBITで区間総和を高速に処理する方法をやっていきます。


class BIT():

def cnt2(self, I): #2で何回割れるか計算する
k = 0
while I % 2 == 0:
k += 1
I = I // 2
return k

def __init__(self, n, A): #BITの作成
self.Tree = [0]* (n + 1) #0で初期化
self.n = n
for i in range(1, n + 1):
k=self.cnt2(i)
for j in range(i - 2 ** k, i): #インデックス注意
self.Tree[i] += A[j]

def add(self, id, x): #A[id]にxを足す作業
self.Tree[id] += x
now = id
while True:
k = self.cnt2(now)
now = now + 2 ** k #親に移動
if now > self.n: #該当するものがないなら根にたどり着いたということ
break
self.Tree[now] += x #加算処理

def sum(self, id): #A[id] までの累積和を計算
#問題 6,7 で実装


(BITの区間総和について)



区間総和について考えていきます。

前から m 項の和をBITの要素の和として計算することを考えます。

まず、j > m を満たす任意の j について、BIT_j には A_j が加算されているので、ここの部分を使うことはできません。

よって、BIT_j (j ≦ m) の要素のみを考えていきます。

A_m の要素は BIT_m にしか含まれていないので、BIT_m を使う必要があります。

また、BIT_m には、m を 2 で割ることが出来る回数の最大値を p としたとき、A_{m - 2 ^ p + 1} から A_m までの 2 ^ p 個の要素の総和が入っています。つまり、前から m 項の和は前から m - 2 ^ p 項の和と BIT_m の和で表すことが出来ます。

そして、前から m - 2 ^ p 項の和は、m を m - 2 ^ p と置きかえて同様に計算することになり、以後 m が 0 になるまで繰り返し計算することになります。

では、実際にインデックス計算を行いましょう。

(問題)



Q 個のクエリが与えられます。順番に処理してください。i (1 ≦ i ≦ Q) 番目のクエリは以下の通りです。

  • 整数 t_i が与えられる。m_0 = t_i とし、m_{i + 1} = m_i - 2 ^ p_i (p_i は m_i を 2 で割ることが出来る回数の最大値)とし、ある整数 k においてはじめて m_k = 0 になったとする。配列 M = (m_0, m_1, ..., m_k) を出力する。
  • 入力される値

    入力は以下のフォーマットで与えられます。


    Q
    t_1
    t_2
    ...
    t_Q


  • 1 行目には 1 つの整数 Q が与えられます。

  • 1 + i (1 ≦ i ≦ Q) 行目には 1 つの整数 t_i が与えられます。

  • 入力は合計 1 + Q 行からなり、入力値最終行の末尾に改行を 1 つ含みます。

  • 入力値最終行の末尾に改行が1つ入ります。
    文字列は標準入力から渡されます。 標準入力からの値取得方法はこちらをご確認ください
    期待する出力

    答えを Q 行で出力してください。

    i (1 ≦ i ≦ Q) 行目には、i 番目のクエリの答えを出力してください。

    条件

    すべてのテストケースについて以下の条件を満たします。


    • 1 ≦ Q ≦ 20000

    • 1 ≦ t_i ≦ 10 ^ 9 (1 ≦ i ≦ Q)

    入力例1

    8
    10
    25
    77
    7
    1
    2
    63
    64

    出力例1

    10 8 0
    25 24 16 0
    77 76 72 64 0
    7 6 4 0
    1 0
    2 0
    63 62 60 56 48 32 0
    64 0

    問題一覧へ戻る

    ページの先頭へ戻る