Speed up b-tree

218 views Asked by At

I wrote a simple implementation of a b-tree, and the problem is that it is too slow (tl9 on codeforces). What should i change to speed up this tree?

The memory limit problem can be easily fixed by increasing the constant b, but then there are time limit problems.

    class BtreeSimple
    {
        public Bnode root = new Bnode(true);
        private static int counter;
 
        public void Add(int key)
        {
            var (overkey, overflow, overvalue) = root.Insert(key, counter);
            counter++;
            if (overflow == null)
                return;
            root = new Bnode(false) {Count = 1, Keys = {[0] = overkey}, Vals = {[0] = overvalue}, Kids = {[0] = root, [1] = overflow}};
        }
    }
 
    class Bnode
    {
        const int b = 16;
        public int Count;
        public int[] Keys = new int[2 * b + 1];
        public Bnode[] Kids;
        public Bnode(bool leaf) => Kids = leaf ? null : new Bnode[2 * b + 2];
        public int[] Vals = new int[2 * b + 1];
 
        public (int, Bnode, int) Insert(int key, int value)
        {
            var i = GetKeyPosition(key);
            if (Kids == null) return InsertAt(i, key, null, value);
            var (overkey, overflow, overvalue) = Kids[i].Insert(key, value);
            return overflow == null ? (0, null, 0) : InsertAt(i, overkey, overflow, overvalue);
        }
 
        private int GetKeyPosition(int key)
        {
            var i = 0;
            while (i < Count && Keys[i] < key)
                i++;
            return i;
        }
 
        private (int, Bnode, int) InsertAt(int i, int key, Bnode keyNode, int value)
        {
            Array.Copy(Keys, i, Keys, i + 1, Count - i);
            Keys[i] = key;
            Vals[i] = value;
            if (keyNode != null)
            {
                Array.Copy(Kids, i + 1, Kids, i + 2, Count - i);
                Kids[i + 1] = keyNode;
            }
            return ++Count <= 2 * b ? (0, null, 0) : Split();
        }
 
        private (int, Bnode, int) Split()
        {
            var split = new Bnode(Kids == null) { Count = b };
            Array.Copy(Keys, b + 1, split.Keys, 0, b);
            Array.Copy(Vals, b + 1, split.Vals, 0, b);
            if (Kids != null)
                Array.Copy(Kids, b + 1, split.Kids, 0, b + 1);
            Count = b;
            return (Keys[b], split, Vals[b]);
        }
 
        public int FindNearest(int key)
        {
            var i = GetKeyPosition(key);
            if (Keys[i] == key)
                return Vals[i];
            if (Kids != null)
                return Kids[i].FindNearest(key);
            if (i >= Count)
                return Vals[i - 1]+1;
            if (Keys[i] < key)
                return Vals[i] + 1;
            return Vals[i];
        }
    }

We have a sorted array (for example arr = [8, 9, 10, 11, 15, 17, 20]) and keys (for example keys = [7, 10, 21, 20]). The task is to tell how many keys from arr are less than keys[i] for each i. For this purpose I made a methdod "FindNearest". Everything else in the code is just pure b-tree.

0

There are 0 answers