0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Binary Indexed Tree

Posted at

BITはセグメント木の機能を限定したものであり、実装が簡単でメモリを節約できる

//数列a(a[0],a[1],…,a[n-1])についての区間和と点更新を扱う
//区間和,点更新,二分探索はO(log{n})で動作する
class BIT {
public:
    //データの長さ
    ll n;

    //データの格納先
    vector<ll> a;//(1の最小bitの桁)個数分の範囲和を持つ

    //コンストラクタ
    BIT(ll n) :n(n), a(n + 1, 0) {}

    //a[i]にxを加算する
    void add(ll i, ll x) {
        i++;
        if (i == 0) return;
        for (ll k = i;k <= n;k += (k & -k)) {//下から上
            a[k] += x;
        }
    }

    //a[i]+a[i+1]+…+a[j]を求める
    ll sum(ll i, ll j) {
        return sum_sub(j) - sum_sub(i - 1);
    }

    //a[0]+a[1]+…+a[i]を求める
    ll sum_sub(ll i) {
        i++;
        ll s = 0;
        if (i == 0) return s;

        for (ll k = i;k > 0;k -= (k & -k)) {//上から下
            s += a[k];
        }
        return s;
    }

    //a[0]+a[1]+…+a[i]>=xとなる最小のiを求める(任意のkでa[k]>=0が必要)
    ll lower_bound(ll x) {
        if (x <= 0) {
            //xが0以下の場合は該当するものなし→0を返す
            return 0;
        }
        else {
            ll i = 0;ll r = 1;
            //最大としてありうる区間の長さを取得する
            //n以下の最小の二乗のべき(BITで管理する数列の区間で最大のもの)を求める
            while (r < n) r = r << 1;
            //区間の長さは調べるごとに半分になる
            for (int len = r;len > 0;len = len >> 1) {
                //その区間を採用する場合
                if (i + len < n && a[i + len] < x) {
                    x -= a[i + len];
                    i += len;
                }
            }
            return i;
        }
    }
};
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?