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

Автор 1zaid1, история, 2 года назад, По-английски

I'm referring to this binary search

int L = 0, R = n;
while (L < R) {
    int m = (l+r)/2;
    if (F(m)) {
        L = m+1;
    } else {
        R = m;
    }
} return L;

Why conventional Binary seach sucks:

A. There are multiple potential off-by-one errors in it. B. It looks ugly. C. It's not the most intuitive approach.

My binary search:

int x = 0, j = *closest power of two higher than the desired range length*;
while (j/=2) {
    if (!F(x+j)) x += j;
} return x+1;

The intuition: We have a function F(x) that begins to be satisfied at some point P. We want to identify P. We'll aim to go as close to it as possible without touching it, so we'll jump j steps forward and see if we touch the satasfied region; if we do, we won't jump; if we don't, we will. This will put us one step behind P, so we will just add one.

The picture shows an example where the range is 16 and the function is satisfied when x >= 6. We'll attempt leaping a size 8 jump, but the function will be satisfied at that time, so we won't. Then we'll try a size 4 leap and succeed, and so on. Finally, x = 5 represents the greatest x at which the function is not satisfied.

This method achieves the exact same purpose without any areas for off by one errors and I find it much more intuitive than the standared range binary search.

  • Проголосовать: нравится
  • +14
  • Проголосовать: не нравится

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

Will j=n; also work, if I am too lazy to find the appropriate power of 2? I think it should work too.

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

    Can you try $$$n = 31$$$, where the answer is supposed to be $$$30$$$?

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

      This indeed does output 27 instead of 30. Good find. What'd be a quick fix? One could replace if(F(x+j)) with while(F(x+j)). (Or one could just always use j=1<<30?)

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

This technique is already discussed once on this blog, but I did think it's significant enough to have its own post. One interesting thing about this technique that hasn't been mentioned there or (UPD: It's linked there) here, is that this would probably be the only method you would be using when you binary search on a BIT. (You can think of how it's possible by thinking of how the BIT works.)

UPD again: oh yeah also you can extend this to real values, where the jumping distance starts with $$$0.5(r-l)$$$

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

    It should be clear from the discussion in that post on how to implement binary search iteratively on a segment tree. Also, I had linked a post about binary lifting on Fenwick trees there too, which does the same kind of binary search.

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

It's just BS with binary lifting, isn't it?

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

    yes it's probably called meta binary search

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

      It's not a meta one. It's just called binary lifting. Congrats to the blog writer that he discovered the method by himself.

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

I'm really surprised no one mentioned the technique is explained here: Competitive Programmer’s Handbook.
Anyways the book is extremely recommended if you have time take a look at it.

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

    The author of the blog I linked in this comment is the author of that book, so yeah. I agree about the book, it's great for beginners.

»
21 месяц назад, # |
  Проголосовать: нравится -8 Проголосовать: не нравится

your binary search doesnt work try n=31

  • »
    »
    21 месяц назад, # ^ |
    Rev. 5   Проголосовать: нравится 0 Проголосовать: не нравится

    I recommend you read the other comments in this comment-thread.

    Also the algorithm from the blog author should also work with $$$n=31=16+8+4+2+1$$$ because $$$j=32$$$.

»
21 месяц назад, # |
Rev. 2   Проголосовать: нравится +1 Проголосовать: не нравится

You can just use the conventional way but make it R-the precision required and L=M instead to avoid any off by one errors. Also, I feel binary search was intuitive as it’s probably the only algorithm I was able to come up with before knowing what it was.

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

Clearly this binary search implementation is meant for finding the maximum value of x, what about finding the minimum?