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

Автор lrvideckis, история, 3 года назад, По-английски

Hi Codeforces! If you calculate midpoint like

int get_midpoint(int l, int r) {//[l, r)
	int pow_2 = 1 << __lg(r-l);//bit_floor(unsigned(r-l));
	return min(l + pow_2, r - pow_2/2);
}

then your segment tree requires only $$$2 \times n$$$ memory.

test
proof

I was inspired by ecnerwala's in_order_layout https://github.com/ecnerwala/cp-book/blob/master/src/seg_tree.hpp

I'll be waiting for some comment "It's well known in china since 2007" 😂

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

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

Thats cool, you're decomposing the segtree into perfect binary trees, not actually caring if the sizes are the same. It gives me some new intuition on the subject.

»
3 года назад, скрыть # |
 
Проголосовать: нравится +5 Проголосовать: не нравится
»
3 года назад, скрыть # |
 
Проголосовать: нравится -20 Проголосовать: не нравится

Segment tree is always 2n memory. I don't get what is new...

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

In fact you can label [l, r] with (l + r | (l != r)), the labels also lay in [2, 2n]

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

You can do this also: let the root be the node $$$0$$$ and let the neighbors for any node $$$x$$$ be $$$x + 1$$$ for the left child, and $$$x + 2(m - l + 1)$$$ for the right child (where $$$[l, r] $$$ is the range which node $$$x$$$ is responsible for, and $$$m$$$ is $$$(l + r) / 2$$$). Also, this is exactly the DFS traversal order of the segment tree.

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

    That's a really cool trick. It should also slightly improve cache hits when going to the left son (although not by a large amount). This is how tourist's segment tree is implemented, btw.

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

This trick is actually pretty cool. I played around with this for a while and got AC a sweepline problem that I got MLE weeks ago. With that said, is there any way, any more tricks that could make this thing faster? Like, I benchmark this method of choosing mid-point, versus the classic method and the latter is around 20% faster, despite consuming twice as much memory (probably because the old method divide the segment into half, making the $$$log$$$ constant per query smaller). Is there any kind of recursive segment tree implementation that is both fast and memory-efficient at the same time?