Submission #1292044

#TimeUsernameProblemLanguageResultExecution timeMemory
1292044cnam9Bigger segments (IZhO19_segments)C++20
0 / 100
0 ms332 KiB
#include <iostream>
#include <vector>

using namespace std;

constexpr int N = 5e5 + 5;
long long s[N];
int f[N];
long long g[N];

template <class KeyType, class ValueType, int B = 64, ValueType IDENTITY_VALUE = {}>
class BTree {

    struct Node;
    std::vector<Node> pool;

    struct Node {
        int size;
        ValueType max_value;
        // +1 for overflow
        std::pair<KeyType, ValueType> items[B + 1];
        Node *children[B + 2];

        void pull() {
            max_value = IDENTITY_VALUE;
            for (int i = 0; i < size; ++i) {
                max_value = std::max(max_value, items[i].second);
            }
            for (int i = 0; i <= size; ++i) {
                if (children[i]) {
                    max_value = std::max(max_value, children[i]->max_value);
                }
            }
        }
    };

    int size;
    Node *root;

    template <class T>
    class BufferedStack {
        std::vector<T> buf;
        int sz;

    public:

        BufferedStack() { }
        ~BufferedStack() = default;

        void reserve(int max_items) {
            buf.resize(max_items);
            sz = 0;
        }

        bool empty() const { return sz == 0; }
        void clear() { sz = 0; }
        void pop() { --sz; }
        void push(T value) { buf[sz++] = value; }
        T &top() { return buf[sz - 1]; }
        const T &top() const { return buf[sz - 1]; }
    };

    BufferedStack<pair<Node *, int>> call_stack;

public:

    BTree(int max_items = 0) : size(0), root(NULL) {
        int max_nodes = 1;
        while (max_items > 1 + (max_nodes - 1) * (B / 2)) max_nodes++;
        pool.resize(max_nodes);

        constexpr int t = B / 2 + 1;

        int max_height = 1;
        long long tpow = 1;
        while (max_items + 1 > 2 * tpow) {
            max_height++;
            tpow *= t;
        }
        call_stack.reserve(max_height + 1);
    }

    ~BTree() = default;

    void insert(KeyType key, ValueType value) {
        call_stack.clear();
        call_stack.push({root, 0});

        while (true) {
            Node *node = call_stack.top().first;
            if (node == NULL) {
                call_stack.pop();
                break;
            }

            node->max_value = std::max(node->max_value, value);

            int i = 0;
            while (i < node->size && node->items[i].first < key) {
                i++;
            }
            if (i < node->size && node->items[i].first == key) {
                node->items[i].second = std::max(node->items[i].second, value);
                return;
            }
            call_stack.top().second = i;
            call_stack.push({node->children[i], 0});
        }

        Node *returned = NULL;

        while (!call_stack.empty()) {
            auto [node, pos] = call_stack.top();
            call_stack.pop();

            for (int i = node->size; i > pos; i--) {
                node->items[i] = node->items[i - 1];
            }
            node->items[pos] = {key, value};

            node->size++;
            for (int i = node->size; i > pos; i--) {
                node->children[i] = node->children[i - 1];
            }
            node->children[pos] = returned;

            if (node->size <= B) {
                return;
            }

            // node overflow
            key = node->items[B / 2].first;
            value = node->items[B / 2].second;

            Node *newnode = &pool[size++];
            newnode->size = B / 2;
            for (int i = 0; i < B / 2; i++) {
                newnode->items[i] = node->items[i];
            }
            for (int i = 0; i <= B / 2; i++) {
                newnode->children[i] = node->children[i];
            }

            node->size = B / 2;
            for (int i = B / 2 - 1; i >= 0; i--) {
                node->items[i] = node->items[i + B / 2 + 1];
            }
            for (int i = B / 2; i >= 0; i--) {
                node->children[i] = node->children[i + B / 2 + 1];
            }
    
            node->pull();
            newnode->pull();
            returned = newnode;
        }

        // root overflow
        Node *newroot = &pool[size++];
        newroot->size = 1;
        newroot->items[0] = {key, value};
        newroot->children[0] = returned;
        newroot->children[1] = root;
        root = newroot;
    }

    ValueType query(KeyType key) {
        if (!root) return IDENTITY_VALUE;

        ValueType result = IDENTITY_VALUE;
        Node *node = root;

        while (node) {
            bool descended = false;

            for (int i = 0; i < node->size; ++i) {
                if (node->items[i].first <= key) {
                    result = std::max(result, node->items[i].second);

                    if (node->children[i]) {
                        result = std::max(result, node->children[i]->max_value);
                    }
                } else {
                    node = node->children[i];
                    descended = true;
                    break;
                }
            }

            if (descended) continue;
            if (!node->children[node->size]) {
                break;
            }
            node = node->children[node->size];
        }

        return result;
    }
};

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    // freopen("input.txt", "r", stdin);

    int n;
    cin >> n;

    BTree<long long, pair<int, long long>, 64> btree(n);

    s[0] = f[0] = g[0] = 0;

    for (int i = 1; i <= n; i++) {
        btree.insert(g[i - 1] + s[i - 1], {f[i - 1], s[i - 1]});

        cin >> s[i];
        s[i] += s[i - 1];

        auto [maxf, maxs] = btree.query(s[i]);
        f[i] = maxf + 1;
        g[i] = s[i] - maxs;
    }

    cout << n - f[n];

    return 0;
}
#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...