2

このコードを理解しようとしていました。セグメント ツリー データ構造のバリアントを使用していると思いますが、このコードのビット操作を理解できません。

実際の問題は、N 個のコインがあり、1 つの操作と 1 つのクエリがあるということです。

  1. [A,B]の範囲でコインを投げる
  2. それぞれ範囲 [A,B] 内の頭の数を見つける。

.

 #define LEAVES (131072)
 #define MSB_V (0x80000000)
 #define MSB_P (31)

 int it[2 * LEAVES];
 int A, B;    //Query range

 void flip (int i, int min, int max)
 {
    if ((min > B) || (max <= A))
    {   }
    else if ((min >= A) && ((max-1) <= B))
    {   it[i] ^= MSB_V; }
    else
    {
        int l = 2 * i;
        int r = l + 1;
        int mid = (min + max) / 2;
        it[l] ^= it[i] & MSB_V;
        it[r] ^= it[i] & MSB_V;
        it[i] ^= MSB_V;
        flip(l, min, mid);
        flip(r, mid, max);
        it[i] = (it[l] >> MSB_P ? mid - min - (it[l] ^ MSB_V) : it[l]) +
                (it[r] >> MSB_P ? max - mid - (it[r] ^ MSB_V) : it[r]);
    }
}

int count (int i, int min, int max)
{
    int h;
    if ((min > B) || (max <= A))
    {   h = 0; }
    else if ((min >= A) && ((max-1) <= B))
    {   h = it[i] >> MSB_P ? max - min - (it[i] ^ MSB_V) : it[i]; }
    else
    {
        int l = 2 * i;
        int r = l + 1;
        int mid = (min + max) / 2;
        it[l] ^= it[i] & MSB_V;
        it[r] ^= it[i] & MSB_V;
        it[i] ^= MSB_V;
        it[i] = (it[l] >> MSB_P ? mid - min - (it[l] ^ MSB_V) : it[l]) +
                (it[r] >> MSB_P ? max - mid - (it[r] ^ MSB_V) : it[r]);
        h = count(l, min, mid) + count(r, mid, max);
    }
    return h;
}

これらすべてのビット操作の背後にあるロジックについて、ヒントを教えてください。

4

1 に答える 1