OI XXVIII - ple

// https://szkopul.edu.pl/problemset/problem/LRxIzCCc5Nn4UvWV514zro4a/site/
#include <bits/stdc++.h>
using namespace std;
#define int long long

struct Node {
    int base; // Base value without deltas
    int delta; // Lazy delta to propagate
    int priority; // For Treap heap property
    int size; // Size of the subtree
    Node *left, *right;

    Node(int val) : base(val), delta(0), priority(rand()), size(1), left(nullptr), right(nullptr) {}
};

class BalancedBST {
private:
    Node* root;

    int getSize(Node* node) { return node ? node->size : 0; }

    void updateSize(Node* node) {
        if (node) node->size = 1 + getSize(node->left) + getSize(node->right);
    }

    void propagate(Node* node) {
        if (!node || node->delta == 0) return;

        node->base += node->delta;
        if (node->left) node->left->delta += node->delta;
        if (node->right) node->right->delta += node->delta;

        node->delta = 0;
    }

    void split(Node* root, int k, Node*& left, Node*& right) {
        propagate(root);
        if (!root) {
            left = right = nullptr;
            return;
        }

        int leftSize = getSize(root->left);
        if (k <= leftSize) {
            split(root->left, k, left, root->left);
            right = root;
        } else {
            split(root->right, k - leftSize - 1, root->right, right);
            left = root;
        }
        updateSize(root);
    }

    Node* merge(Node* left, Node* right) {
        propagate(left);
        propagate(right);

        if (!left) return right;
        if (!right) return left;

        if (left->priority > right->priority) {
            left->right = merge(left->right, right);
            updateSize(left);
            return left;
        } else {
            right->left = merge(left, right->left);
            updateSize(right);
            return right;
        }
    }

    Node* insert(Node* node, int x) {
        if (!node) return new Node(x);

        propagate(node);

        if (x <= node->base) {
            node->left = insert(node->left, x);
            if (node->left->priority > node->priority) {
                Node* rotated = node->left;
                propagate(rotated);
                node->left = rotated->right;
                rotated->right = node;
                updateSize(node);
                updateSize(rotated);
                node = rotated;
            }
        } else {
            node->right = insert(node->right, x);
            if (node->right->priority > node->priority) {
                Node* rotated = node->right;
                propagate(rotated);
                node->right = rotated->left;
                rotated->left = node;
                updateSize(node);
                updateSize(rotated);
                node = rotated;
            }
        }

        updateSize(node);
        return node;
    }

    int lowerBound(Node* node, int x) {
        int idx = 0, result = getSize(node);
        Node* curr = node;

        while (curr) {
            propagate(curr);
            int currLeftSize = getSize(curr->left);

            if (x <= curr->base) {
                result = idx + currLeftSize;
                curr = curr->left;
            } else {
                idx += currLeftSize + 1;
                curr = curr->right;
            }
        }

        return result;
    }

    void inOrder(Node* node) {
        if (!node) return;
        propagate(node);
        inOrder(node->left);
        cout << node->base << " ";
        inOrder(node->right);
    }

public:
    BalancedBST() : root(nullptr) { srand(time(0)); }

    void insert(int x) { root = insert(root, x); }

    int findFirstGeq(int x) { return lowerBound(root, x); }

    void addToSuffix(int j, int delta) {
        Node *left = nullptr, *right = nullptr;
        split(root, j, left, right);
        if (right) right->delta += delta;
        root = merge(left, right);
    }

    void print() {
        inOrder(root);
        cout << endl;
    }

    void insertAtJPlusP(int j, int p) {
        Node *left, *right;
        split(root, j + 1, left, right); // Split after position j

        Node *left_part, *a_j_node;
        split(left, j, left_part, a_j_node); // Extract a[j]

        propagate(a_j_node); // Ensure we get current value
        Node* new_node = new Node(a_j_node->base + p);

        // Merge: left_part + a_j_node + new_node + right
        root = merge(merge(merge(left_part, a_j_node), new_node), right);
    }
};

int32_t main() {
    std::ios_base::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);

    BalancedBST tree;

    int n;
    std::cin >> n;

    std::vector<int> v(n);
    for (auto& a : v) {
        std::cin >> a;
    }

    tree.insert(*v.rbegin());

    int curr_size = 1;
    for (int i = n - 2; i >= 0; i--, curr_size++) {
        int idx = tree.findFirstGeq(v[i]);
        if (idx + 1 <= curr_size) {
            tree.addToSuffix(idx, v[i]);
        }

        if (idx == 0) {
            tree.insert(v[i]);
        } else {
            tree.insertAtJPlusP(idx - 1, v[i]);
        }
    }

    tree.print();

    return 0;
}