Блог пользователя rng_50216

Автор rng_50216, 12 лет назад, По-английски

Does anyone have implementation of BIT for following operations:

setmin(i, x) = a[i] := min(a[i], x)

getmin(l, r) = min(a[x], l <= x <= r)

Does anyone have implementation of BIT for following operations:

add(l, r, x) = a[i] += x, where l <= i <= r

getsum(l, r) = sum(a[i]), where l <= i <= r

Теги bit
  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

»
12 лет назад, # |
  Проголосовать: нравится -13 Проголосовать: не нравится

These operations are not supported by BIT. Use segment tree instead.

  • »
    »
    12 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится -17 Проголосовать: не нравится

    Let's wait for more experienced coders.

    There are the ways, that use more memory and time for doing that operations using BIT, but it's still faster than using segment tree.

»
12 лет назад, # |
Rev. 5   Проголосовать: нравится +19 Проголосовать: не нравится

For the second problem:

let y[i] = x[i]-x[i-1] let z[i] = y[i] * i

for example sum(1..3) x[i] = x[1] + x[2] + x[3] x[1] = x[1] x[2] = y[2] + y[1]; x[3] = y[3] + y[2] + y[1]

so x[1]+x[2]+x[3] = 4(y[1]+y[2]+y[3])-1*x[1]-2 * x[2]-3 * x[3] = 4 * (y[1] + y[2] + y[3])-(z[1] + z[2] + z[3])

we can infer that

sum(1..n) x[i] = sum(1..n) n * y[i]-sum(1..n) i * y[i] = sum(1..n) n * y[i]-sum(1..n) z[i]

notice that each modification can modify at most two elements of y[] and z[] so we can use two BITs to maintain y[] and z[]

»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

For the first problem:

if l is always the first element of a[], then the normal BIT can support these operations easily. but I can't come up with ideas when l can be other element.

  • »
    »
    12 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +2 Проголосовать: не нравится

    It won't do. Once you try to increase element, there is no reliable way to determine the new value for all intervals, which contain it. You can only decrease elements in this case.

    Upd. Sorry, didn't notice min(a[i],x) in topic

»
12 лет назад, # |
Rev. 3   Проголосовать: нравится +5 Проголосовать: не нравится

for the first one there is easy to remember short code

const int N = 1 << 17; // has to be power of 2
const int inf = 1 << 28;

struct RMQ {
    int a[N * 2];
    RMQ() {
        FOR(i, N * 2)
            a[i] = inf;
    }
    void SetMin(int pos, int x) {
        for (int i = pos + N; i; i >>= 1)
            a[i] = min(a[i], x);
    }
    int GetMin(int L, int R) const // [L, R) i.e. L <= i < R
    {
        int res = inf;
        for (L += N, R += N; L < R; L >>= 1, R >>= 1) {
            if (L & 1) {
                res = min(res, a[L]);
                L++;
            }
            if (R & 1) {
                R--;
                res = min(res, a[R]);
            }
        }
        return res;
    }
};
  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится -8 Проголосовать: не нравится

    Yes, thanks. I've seen you wrote that in another blog.

    But I still want to learn, how to do it easily using BIT.

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Could you please explain how this works ? And why do N have to be power of 2 ?

»
12 лет назад, # |
  Проголосовать: нравится +2 Проголосовать: не нравится

Can you explain what is BIT? Is it binary search tree or Fenwick tree?

»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

For the second problem I found this very short implementation some time ago, but I didn't analyze it.

typedef long long int lld;
const int MaxN = 1 << 18;


int N;
lld BIT[MaxN][2];

inline void Update ( int idx, lld Value )
{
    for ( int i = idx; i <= N; i += i & -i )
    {
        BIT[i][0] += ( i - idx + 1LL ) * Value;
        BIT[i][1] += Value;
    }
}

inline lld Query ( int idx )
{
    lld Ret = BIT[idx][0];
    for ( int i = idx - ( idx & -idx ); i; i -= i & -i ) Ret += BIT[i][0] + ( idx - i ) * BIT[i][1];
    return Ret;
}
»
12 лет назад, # |
Rev. 7   Проголосовать: нравится -7 Проголосовать: не нравится

For the first problem:

Obviously, setmin(i, x) can be rewritten as setvalue(i, x) if x < a[i], or otherwise ignore the operation. setvalue(i, x) = a[i] := x.

Next, I keep 2 arrays T and a. a is the current array, while T is my Fenwick tree. But instead of keeping minimal value of a range in the Fenwick, I keep index of that value in the a array.

define bit(i) (i & -i)

int que( int l, int r ) { //returns the index of the minimal value in a

int m = 0;
 while( l <= r )
    if( r-bit(r)+1 >= l ) //the interval is fully contained into [l, r]
    {
        if(a[m] < a[ T[r] ]) m = T[r];
        r -=bit(r);
    }
    else
    {
        if(a[m] < a[r]) m = r; //I can't use the fenwick information, so I have to process a single //element
        r--; 
    }
return m;

}

void upd( int x, int val ) {

int y, z;
a[x] = val;
for(y = x; x <= N; x += bit(x)) //y is index of updated element, x is the current fenwick.
    if(T[x] == y) //this should be used for general update cases, for setmin operations it's //useless. About setmin, I'll always be sure that if last value was the best for range, then new //value will also be the good one for range, since the new one is smaller then the last one.
    { //from here I suppose the updated value is greater than last one. 
        z = que(x-bit(x) + 1, x-1); //this takes O(logN) time
        T[x] = (a[z] > a[x]) ? z : x; //the minimal value from the range [x - bit(x) + 1, x] is //minimal between x and [x - bit(x) + 1, x - 1].
    }
    else //just check and update like in normal fenwick version.
    if(a[ T[x] ] < a[ y ])T[x] = y;

}

Both operations run in O(log^2) time worst case. However, execution time for big inputs is comparable with times of segment trees.