Submission #300289

#TimeUsernameProblemLanguageResultExecution timeMemory
300289marXComparing Plants (IOI20_plants)C++17
44 / 100
673 ms14584 KiB
#include <vector>
#include <set>
#include <iostream>
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstring>
#include <functional>
#include <fstream>
#include <iomanip>

#include <istream>

#include <map>
#include <math.h>
#include <numeric>
#include <ostream>
#include <queue>

#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>

namespace asl
{

    void fin(std::string word)
    {
        std::cout << word << std::endl;
        std::exit(0);
    }

} // namespace asl

#include <stdint.h>

#include <experimental/optional>
#define optional std::experimental::optional

namespace asl
{

    template <typename T, typename U = T>
    class SegmentTree
    {
        int size;
        std::function<void(T &, U &)> _update;
        std::function<T(T &, T &)> _merge;
        std::function<optional<U>(T &)> _get_lazy;

        void push(int p, int l, int r)
        {
            auto lazy = _get_lazy(ds[p]);

            if (lazy)
            {
                _update(ds[l], *lazy);
                _update(ds[r], *lazy);
            }
        }

        void update(int p, int b, int e, int x, int y, U &upd)
        {
            if (x <= b && e <= y)
            {
                _update(ds[p], upd);
            }
            else
            {
                int m = (b + e) >> 1, l = p + 1, r = p + ((m - b) << 1);

                push(p, l, r);

                if (x < m)
                    update(l, b, m, x, y, upd);

                if (m < y)
                    update(r, m, e, x, y, upd);

                ds[p] = _merge(ds[l], ds[r]);
            }
        }

        T query(int p, int b, int e, int x, int y)
        {
            if (x <= b && e <= y)
            {
                return ds[p];
            }
            else
            {
                int m = (b + e) >> 1, l = p + 1, r = p + ((m - b) << 1);

                push(p, l, r);

                if (x < m)
                {
                    auto le = query(l, b, m, x, y);

                    if (m < y)
                    {
                        auto ri = query(r, m, e, x, y);
                        return _merge(le, ri);
                    }
                    else
                    {
                        return le;
                    }
                }
                else
                {
                    return query(r, m, e, x, y);
                }
            }
        }

        void build(int p, int b, int e, std::function<T(int)> &builder)
        {
            if (b + 1 == e)
            {
                ds[p] = builder(b);
            }
            else
            {
                int m = (b + e) >> 1, l = p + 1, r = p + ((m - b) << 1);

                build(l, b, m, builder);
                build(r, m, e, builder);

                ds[p] = _merge(ds[l], ds[r]);
            }
        }

        void init(int size,
                  std::function<void(T &, U &)> update,
                  std::function<T(T &, T &)> merge,
                  std::function<optional<U>(T &)> get_lazy)
        {
            this->size = size;
            this->_update = update;
            this->_merge = merge;
            this->_get_lazy = get_lazy;
            this->ds = std::vector<T>(2 * size - 1);
        }

    public:
        std::vector<T> ds;

        SegmentTree(
            int size,
            std::function<void(T &, U &)> update,
            std::function<T(T &, T &)> merge = [](T &l, T &r) { return l + r; },
            std::function<optional<U>(T &)> get_lazy = [](T &value) { return optional<U>(); })
        {
            init(size, update, merge, get_lazy);
        }

        void build(std::function<T(int)> builder)
        {
            build(0, 0, size, builder);
        }

        void update(int x, U upd)
        {
            update(0, 0, size, x, x + 1, upd);
        }

        void update(int x, int y, U upd)
        {
            update(0, 0, size, x, y, upd);
        }

        T query(int x, int y)
        {
            return query(0, 0, size, x, y);
        }
    };
} // namespace asl

#include <tuple>

#include <random>

#include <utility>

using namespace std;
using namespace asl;

vector<int> xrank;

struct state
{
    int value, left, right, max_diff, index, lazy;
};

void init(int k, vector<int> r)
{
    int n = r.size();
    xrank.resize(n);

    SegmentTree<state, int> st(
        n, [&](state &s, int &u) { s.value += u; s.lazy += u; },
        [&](state &l, state &r) { state res;
        if (l.value < r.value) {
            res = l;
            res.lazy = 0;
        } else if (r.value < l.value) {
            res = r;
            res.lazy = 0;
        } else {
            res.value = l.value;
            res.left = l.left;
            res.right = r.right;
            res.max_diff = max({l.max_diff, r.max_diff, r.left - l.right});
            res.lazy = 0;

            if (l.max_diff == res.max_diff) {
                res.index = l.index;
            } else if (r.max_diff == res.max_diff) {
                res.index = r.index;
            } else {
                res.index = r.left;
            }
        }
        return res; },
        [&](state &s) {
            if (s.lazy) {
                int value = s.lazy;
                s.lazy = 0;
                return optional<int>(value);
            } else {
                return optional<int>();
            } });

    st.build([&](int p) {
        state res = {r[p], p, p, 0, p, 0};
        return res;
    });

    for (int i = 0; i < n; ++i)
    {
        auto res = st.query(0, n);
        int wrap_diff = res.left + n - res.right;
        int index = res.index;
        if (wrap_diff > res.max_diff)
            index = res.left;

        xrank[index] = n - i;

        st.update(index, +1e6);

        if (index >= k - 1)
            st.update(index - k + 1, index, -1);
        else
        {
            if (index)
                st.update(0, index, -1);
            st.update(n + index - (k - 1), n, -1);
        }
    }
}

int compare_plants(int a, int b)
{
    return xrank[a] > xrank[b] ? +1 : -1;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...