int
    test() {
	printf("Testing SparseTable implementation\n");
	printf("----------------------------------\n");

        vui_t v;
        v.push_back(45);
        v.push_back(4);
        v.push_back(5);
        v.push_back(2);
        v.push_back(99);
        v.push_back(41);
        v.push_back(45);
        v.push_back(45);
        v.push_back(51);
        v.push_back(89);
        v.push_back(1);
        v.push_back(3);
        v.push_back(5);
        v.push_back(98);

        for (int i = 0; i < 10; ++i) {
            // printf("%d: %d\n", i, log2(i));
        }

        SparseTable st;
        st.initialize(v);

        for (size_t i = 0; i < v.size(); ++i) {
            for (size_t j = i; j < v.size(); ++j) {
                pui_t one = st.query_max(i, j);
                pui_t two = naive_query_max(v, i, j);
                printf("query_max(%u, %u) == (%u, %u)\n", (uint_t)i, (uint_t)j, one.first, two.first);
                assert_eq(one.first, two.first);
            }
        }

	printf("\n");
        return 0;
    }
Esempio n. 2
0
    // qf & ql are indexes; both inclusive.
    // Return: first -> value, second -> index
    pui_t
    query_max(uint_t qf, uint_t ql) {
        if (qf >= this->len || ql >= this->len || ql < qf) {
            return make_pair(minus_one, minus_one);
        }

        if (len < MIN_SIZE_FOR_BENDER_RMQ) {
            return st.query_max(qf, ql);
        }

        DPRINTF("[1] (qf, ql) = (%d, %d)\n", qf, ql);
        // Map to +-RMQ co-ordinates
        qf = mapping[qf];
        ql = mapping[ql];
        DPRINTF("[2] (qf, ql) = (%d, %d)\n", qf, ql);

        if (qf > ql) {
            std::swap(qf, ql);
            DPRINTF("[3] (qf, ql) = (%d, %d)\n", qf, ql);
        }

        // Determine whether we need to query 'st'.
        const uint_t first_block_index = qf / lgn_by_2;
        const uint_t last_block_index = ql / lgn_by_2;

        DPRINTF("first_block_index: %u, last_block_index: %u\n",
                first_block_index, last_block_index);

        pui_t ret(0, 0);

        /* Main logic:
         *
         * [1] If the query is restricted to a single block, then
         * first_block_index == last_block_index, and we only need to
         * do a bitmap based lookup.
         *
         * [2] If last_block_index - first_block_index == 1, then the
         * query spans 2 blocks, and we do not need to lookup the
         * Sparse Table to get the summary max.
         *
         * [3] In all other cases, we need to take the maximum of 3
         * results, (a) the max in the suffix of the first block, (b)
         * the max in the prefix of the last block, and (c) the max of
         * all blocks between the first and the last block.
         *
         */

        if (last_block_index - first_block_index > 1) {
            // We need to perform an inter-block query using the 'st'.
            ret = st.query_max(first_block_index + 1, last_block_index - 1);

            // Now perform an in-block query to get the index of the
            // max value as it appears in 'euler'.
            const uint_t bitmapx = table_map[ret.second];
            const uint_t imax = lt.query_max(bitmapx, 0, lgn_by_2-1) + ret.second*lgn_by_2;
            ret.second = imax;
        } else if (first_block_index == last_block_index) {
            // The query is completely within a block.
            const uint_t bitmapx = table_map[first_block_index];
            DPRINTF("bitmapx: %s\n", bitmap_str(bitmapx).c_str());
            qf %= lgn_by_2;
            ql %= lgn_by_2;
            const uint_t imax = lt.query_max(bitmapx, qf, ql) + first_block_index*lgn_by_2;
            ret = make_pair(euler[imax], rev_mapping[imax]);
            return ret;
        }

        // Now perform an in-block query for the first and last
        // blocks.
        const uint_t f1 = qf % lgn_by_2;
        const uint_t f2 = lgn_by_2 - 1;

        const uint_t l1 = 0;
        const uint_t l2 = ql % lgn_by_2;

        const uint_t bitmap1 = table_map[first_block_index];
        const uint_t bitmap2 = table_map[last_block_index];

        DPRINTF("bitmap1: %s, bitmap2: %s\n", bitmap_str(bitmap1).c_str(),
                bitmap_str(bitmap2).c_str());

        uint_t max1i = lt.query_max(bitmap1, f1, f2);
        uint_t max2i = lt.query_max(bitmap2, l1, l2);

        DPRINTF("max1i: %u, max2i: %u\n", max1i, max2i);

        max1i += first_block_index * lgn_by_2;
        max2i += last_block_index * lgn_by_2;

        if (last_block_index - first_block_index > 1) {
            // 3-way max
            DPRINTF("ret: %u, max1: %u, max2: %u\n", ret.first, euler[max1i], euler[max2i]);
            if (ret.first > euler[max1i] && ret.first > euler[max2i]) {
                ret.second = rev_mapping[ret.second];
            } else if (euler[max1i] >= ret.first && euler[max1i] >= euler[max2i]) {
                ret = make_pair(euler[max1i], rev_mapping[max1i]);
            } else if (euler[max2i] >= ret.first && euler[max2i] >= euler[max1i]) {
                ret = make_pair(euler[max2i], rev_mapping[max2i]);
            }
        } else {
            // 2-way max
            if (euler[max1i] > euler[max2i]) {
                ret = make_pair(euler[max1i], rev_mapping[max1i]);
            } else {
                ret = make_pair(euler[max2i], rev_mapping[max2i]);
            }
        }

        return ret;
    }