Esempio n. 1
0
int main(){
#ifdef LOCAL
    freopen("/Users/apple/input.txt", "r", stdin);
//  freopen("/Users/apple/out.txt", "w", stdout);
#endif
	
    while(si(n) != EOF) {
    	rep(i, n) si(a[i]);
    	minST.build(a, n, MIN);
    	gcdST.build(a, n, GCD);
    	int l = 1, r = n + 1, mid;
    	while(l < r) {
    		mid = (l + r) >> 1;
    		if(check(mid)) l = mid + 1;
    		else r = mid;
    	}
    	int len = l - 1;
    	VI tmp;
    	for(int i = 0; i + len <= n; i ++) {
    		int j = i + len - 1;
    		if(minST.query(i, j) == gcdST.query(i, j)) tmp.pb(i);
    	}
    	int sz = tmp.size();
    	printf("%d %d\n",sz, len - 1);
    	rep(i, sz - 1) printf("%d ", tmp[i] + 1);
    	put(tmp[sz-1] + 1);
    }
    
    return 0;
}
Esempio n. 2
0
// Imp
bool check(int L) {
	for(int i = 0; i + L <= n; i ++) {
		int j = i + L - 1;
		if(minST.query(i, j) == gcdST.query(i, j)) return true;
	}
	return false;
}
Esempio n. 3
0
    /// For each cell, order the (cell) neighbours counterclockwise.
    /// \param[in] grid    A 2d grid object.
    /// \param[in, out] nb A cell-cell neighbourhood table, such as from cellNeighboursAcrossVertices().
    void orderCounterClockwise(const UnstructuredGrid& grid,
                               SparseTable<int>& nb)
    {
        if (grid.dimensions != 2) {
            OPM_THROW(std::logic_error, "Cannot use orderCounterClockwise in " << grid.dimensions << " dimensions.");
        }
        const int num_cells = grid.number_of_cells;
        if (nb.size() != num_cells) {
            OPM_THROW(std::logic_error, "Inconsistent arguments for orderCounterClockwise().");
        }

        // For each cell, compute each neighbour's angle with the x axis,
        // sort that to find the correct permutation of the neighbours.
        typedef std::pair<double, int> AngleAndPos;
        std::vector<AngleAndPos> angle_and_pos;
        std::vector<int> original;
        for (int cell = 0; cell < num_cells; ++cell) {
            const int num_nb = nb[cell].size();
            angle_and_pos.clear();
            angle_and_pos.resize(num_nb);
            for (int ii = 0; ii < num_nb; ++ii) {
                const int cell2 = nb[cell][ii];
                const double v[2] = { grid.cell_centroids[2*cell2] - grid.cell_centroids[2*cell],
                                      grid.cell_centroids[2*cell2 + 1] - grid.cell_centroids[2*cell + 1] };
                // The formula below gives an angle in [0, 2*pi] with the positive x axis.
                const double angle = boost::math::constants::pi<double>() - std::atan2(v[1], -v[0]);
                angle_and_pos[ii] = std::make_pair(angle, ii);
            }
            original.assign(nb[cell].begin(), nb[cell].end());
            std::sort(angle_and_pos.begin(), angle_and_pos.end());
            for (int ii = 0; ii < num_nb; ++ii) {
                nb[cell][ii] = original[angle_and_pos[ii].second];
            }
        }
    }
    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. 5
0
    /// Solve for time-of-flight and a number of tracers.
    /// \param[in]  darcyflux         Array of signed face fluxes.
    /// \param[in]  porevolume        Array of pore volumes.
    /// \param[in]  source            Source term. Sign convention is:
    ///                                 (+) inflow flux,
    ///                                 (-) outflow flux.
    /// \param[in]  tracerheads       Table containing one row per tracer, and each
    ///                               row contains the source cells for that tracer.
    /// \param[out] tof               Array of time-of-flight values (1 per cell).
    /// \param[out] tracer            Array of tracer values. N per cell, where N is
    ///                               equalt to tracerheads.size().
    void TofReorder::solveTofTracer(const double* darcyflux,
                                    const double* porevolume,
                                    const double* source,
                                    const SparseTable<int>& tracerheads,
                                    std::vector<double>& tof,
                                    std::vector<double>& tracer)
    {
        darcyflux_ = darcyflux;
        porevolume_ = porevolume;
        source_ = source;
        const int num_cells = grid_.number_of_cells;
#ifndef NDEBUG
        // Sanity check for sources.
        const double cum_src = std::accumulate(source, source + num_cells, 0.0);
        if (std::fabs(cum_src) > *std::max_element(source, source + num_cells)*1e-2) {
            OPM_THROW(std::runtime_error, "Sources do not sum to zero: " << cum_src);
        }
#endif
        tof.resize(num_cells);
        std::fill(tof.begin(), tof.end(), 0.0);
        tof_ = &tof[0];

        if (use_multidim_upwind_) {
            face_tof_.resize(grid_.number_of_faces);
            std::fill(face_tof_.begin(), face_tof_.end(), 0.0);
            face_part_tof_.resize(grid_.face_nodepos[grid_.number_of_faces]);
            std::fill(face_part_tof_.begin(), face_part_tof_.end(), 0.0);
        }

        // Execute solve for tof
        compute_tracer_ = false;
        executeSolve();

        // Find the tracer heads (injectors).
        const int num_tracers = tracerheads.size();
        tracer.resize(num_cells*num_tracers);
        std::fill(tracer.begin(), tracer.end(), 0.0);
        if (num_tracers > 0) {
            tracerhead_by_cell_.clear();
            tracerhead_by_cell_.resize(num_cells, NoTracerHead);
        }
        for (int tr = 0; tr < num_tracers; ++tr) {
            for (int i = 0; i < tracerheads[tr].size(); ++i) {
                const int cell = tracerheads[tr][i];
                tracer[num_cells * tr + cell] = 1.0;
                tracerhead_by_cell_[cell] = tr;
            }
        }

        // Execute solve for tracers.
        std::vector<double> fake_pv(num_cells, 0.0);
        porevolume_ = fake_pv.data();
        for (int tr = 0; tr < num_tracers; ++tr) {
            tof_ = tracer.data() + tr * num_cells;
            compute_tracer_ = true;
            executeSolve();
        }

        // Write output tracer data (transposing the computed data).
        std::vector<double> computed = tracer;
        for (int cell = 0; cell < num_cells; ++cell) {
            for (int tr = 0; tr < num_tracers; ++tr) {
                tracer[num_tracers * cell + tr] = computed[num_cells * tr + cell];
            }
        }
    }
Esempio n. 6
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;
    }
Esempio n. 7
0
    void initialize(vui_t const& elems) {
        len = elems.size();

        if (len < MIN_SIZE_FOR_BENDER_RMQ) {
            st.initialize(elems);
            return;
        }

        vui_t levels;
        SimpleFixedObjectAllocator<BinaryTreeNode> alloc(len);

        euler.reserve(elems.size() * 2);
        mapping.resize(elems.size());
        BinaryTreeNode *root = make_cartesian_tree(elems, alloc);

        DPRINTF("GraphViz (paste at: http://ashitani.jp/gv/):\n%s\n", toGraphViz(NULL, root).c_str());

        euler_tour(root, euler, levels, mapping, rev_mapping);

        root = NULL; // This tree has now been deleted
        alloc.clear();

        assert_eq(levels.size(), euler.size());
        assert_eq(levels.size(), rev_mapping.size());

        uint_t n = euler.size();
        lgn_by_2 = log2(n) / 2;
        _2n_lgn  = n / lgn_by_2 + 1;

        DPRINTF("n = %u, lgn/2 = %d, 2n/lgn = %d\n", n, lgn_by_2, _2n_lgn);
        lt.initialize(lgn_by_2);

        table_map.resize(_2n_lgn);
        vui_t reduced;

        for (uint_t i = 0; i < n; i += lgn_by_2) {
            uint_t max_in_block = euler[i];
            int bitmap = 1L;
            DPRINTF("Sequence: (%u, ", euler[i]);
            for (int j = 1; j < lgn_by_2; ++j) {
                int curr_level, prev_level;
                uint_t value;
                if (i+j < n) {
                    curr_level = levels[i+j];
                    prev_level = levels[i+j-1];
                    value = euler[i+j];
                } else {
                    curr_level = 1;
                    prev_level = 0;
                    value = 0;
                }

                const uint_t bit = (curr_level < prev_level);
                bitmap |= (bit << j);
                max_in_block = std::max(max_in_block, value);
                DPRINTF("%u, ", value);
            }
            DPRINTF("), Bitmap: %s\n", bitmap_str(bitmap).c_str());
            table_map[i / lgn_by_2] = bitmap;
            reduced.push_back(max_in_block);
        }

        DPRINTF("reduced.size(): %u\n", reduced.size());
        st.initialize(reduced);
        DCERR("initialize() completed"<<endl);
    }