std::deque unusually high memory usage
Difference between en2 and en3, changed 0 character(s)
[problem:101911E]↵

When I first got MLE, I suspected it might be because of `#define int long long`, but even after changing that I still got MLE. I couldn't figure out what was wrong as I was sure that the space was O(n).↵

When I used `std::set` instead of `std::deque` it used only 100MB memory.↵



<spoiler summary="std::deque code">↵
...↵

~~~~~↵
#include <bits/stdc++.h>↵
#include <ext/pb_ds/assoc_container.hpp>↵
#include <ext/pb_ds/tree_policy.hpp>↵

// #define int long long↵
#define float double↵
#define all(x) (x).begin(), (x).end()↵
#define pnl cout << "\n"↵
#ifndef ONLINE_JUDGE↵
#define dbg(x) cerr << (#x) << " " << (x) << "\n"↵
#else↵
#define dbg(x) 42↵
#endif↵

using namespace std;↵
using namespace __gnu_pbds;↵

template <typename T>↵
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;↵
using vi = vector<int>;↵
using vvi = vector<vi>;↵
using ii = array<int, 2>;↵
using vii = vector<ii>;↵

template <typename T>↵
istream &operator>>(istream &in, vector<T> &a) {↵
    for (auto &x : a) in >> x;↵
    return in;↵
}↵
template <typename T>↵
ostream &operator<<(ostream &out, vector<T> &a) {↵
    for (auto &x : a) out << x << " ";↵
    return out;↵
}↵

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());↵

const int inf = numeric_limits<int>::max();↵
struct Node {↵
    Node *l = 0, *r = 0;↵
    int lo, hi, mset = inf, madd = 0, val = 0;↵
    Node(int lo,int hi):lo(lo),hi(hi){} // Large interval of 0↵
    Node(vector<int>& v, int lo, int hi) : lo(lo), hi(hi) {↵
        if (lo + 1 < hi) {↵
            int mid = lo + (hi - lo) / 2;↵
            l = new Node(v, lo, mid); r = new Node(v, mid, hi);↵
            val = l->val + r->val;↵
        }↵
        else val = v[lo];↵
    }↵
    int query(int L, int R) {↵
        if (R <= lo || hi <= L) return 0;↵
        if (L <= lo && hi <= R) return val;↵
        push();↵
        return l->query(L, R) + r->query(L, R);↵
    }↵
    void set(int L, int R, int x) {↵
        if (R <= lo || hi <= L) return;↵
        if (L <= lo && hi <= R) {↵
            mset = x;↵
            madd = 0;↵
            val = x * (hi - lo);↵
        }↵
        else {↵
            push();↵
            l->set(L, R, x);↵
            r->set(L, R, x);↵
            val = l->val + r->val;↵
        }↵
    }↵
    void add(int L, int R, int x) {↵
        if (R <= lo || hi <= L) return;↵
        if (L <= lo && hi <= R) {↵
            if (mset != inf) mset += x;↵
            else madd += x;↵
            val += x * (hi - lo);↵
        }↵
        else {↵
            push();↵
            l->add(L, R, x);↵
            r->add(L, R, x);↵
            val = l->val + r->val;↵
        }↵
    }↵
    void push() {↵
        if (!l) {↵
            int mid = lo + (hi - lo) / 2;↵
            l = new Node(lo, mid); r = new Node(mid, hi);↵
        }↵
        if (mset != inf) {↵
            l->set(lo, hi, mset);↵
            r->set(lo, hi, mset);↵
            mset = inf;↵
        }↵
        else if (madd) {↵
            l->add(lo, hi, madd);↵
            r->add(lo, hi, madd);↵
            madd = 0;↵
        }↵
    }↵
};↵

void solve(int testcase) {↵
    int n; cin >> n;↵
    vi a(n); cin >> a;↵

    map<int, deque<int>> pos;↵
    for (int i = 0; i < n; i++) {↵
        pos[a[i]].push_back(i);↵
    }↵

    vi op(n);↵
    Node st(a, 0, n);↵
    Node st2(op, 0, n);↵

    int m; cin >> m;↵
    while (m--) {↵
        int clr; cin >> clr;↵
        if (pos.find(clr) == pos.end()) continue;↵

        auto &dq = pos[clr];↵
        if (dq.size() < 2) continue;↵

        while (dq.size()) {↵
            int l = dq.front();↵
            if (st2.query(l, l + 1)) {↵
                dq.pop_front();↵
                continue;↵
            }↵
            break;↵
        }↵
        while (dq.size()) {↵
            int r = dq.back();↵
            if (st2.query(r, r + 1)) {↵
                dq.pop_back();↵
                continue;↵
            }↵
            break;↵
        }↵
        if (dq.size() >= 2) {↵
            int l = dq.front();↵
            int r = dq.back();↵
            st.set(l, r + 1, a[l]);↵
            if (r > l + 1) st2.add(l + 1, r, 1);↵
        }↵
    }↵

    for (int i = 0; i < n; i++) {↵
        cout << st.query(i, i + 1) << " ";↵
    }↵
    pnl;↵
}↵

int32_t main() {↵
    using namespace chrono;↵
    ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);↵
    auto start = high_resolution_clock::now();↵
    int T = 1; // cin >> T;↵
    for (int t = 1; t <= T; t++) {↵
        solve(t);↵
    }↵
    auto end = high_resolution_clock::now();↵
    auto duration = duration_cast<milliseconds>(end - start);↵
#ifndef ONLINE_JUDGE↵
    cerr << "Time: " << duration.count() << " ms\n";↵
#endif↵
    return 0;↵
}↵
~~~~~↵


</spoiler>↵



<spoiler summary="std::set code">↵
...↵

~~~~~↵
#include <bits/stdc++.h>↵
#include <ext/pb_ds/assoc_container.hpp>↵
#include <ext/pb_ds/tree_policy.hpp>↵

// #define int long long↵
#define float double↵
#define all(x) (x).begin(), (x).end()↵
#define pnl cout << "\n"↵
#ifndef ONLINE_JUDGE↵
#define dbg(x) cerr << (#x) << " " << (x) << "\n"↵
#else↵
#define dbg(x) 42↵
#endif↵

using namespace std;↵
using namespace __gnu_pbds;↵

template <typename T>↵
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;↵
using vi = vector<int>;↵
using vvi = vector<vi>;↵
using ii = array<int, 2>;↵
using vii = vector<ii>;↵

template <typename T>↵
istream &operator>>(istream &in, vector<T> &a) {↵
    for (auto &x : a) in >> x;↵
    return in;↵
}↵
template <typename T>↵
ostream &operator<<(ostream &out, vector<T> &a) {↵
    for (auto &x : a) out << x << " ";↵
    return out;↵
}↵

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());↵

const int inf = numeric_limits<int>::max();↵
struct Node {↵
    Node *l = 0, *r = 0;↵
    int lo, hi, mset = inf, madd = 0, val = 0;↵
    Node(int lo,int hi):lo(lo),hi(hi){} // Large interval of 0↵
    Node(vector<int>& v, int lo, int hi) : lo(lo), hi(hi) {↵
        if (lo + 1 < hi) {↵
            int mid = lo + (hi - lo) / 2;↵
            l = new Node(v, lo, mid); r = new Node(v, mid, hi);↵
            val = l->val + r->val;↵
        }↵
        else val = v[lo];↵
    }↵
    int query(int L, int R) {↵
        if (R <= lo || hi <= L) return 0;↵
        if (L <= lo && hi <= R) return val;↵
        push();↵
        return l->query(L, R) + r->query(L, R);↵
    }↵
    void set(int L, int R, int x) {↵
        if (R <= lo || hi <= L) return;↵
        if (L <= lo && hi <= R) {↵
            mset = x;↵
            madd = 0;↵
            val = x * (hi - lo);↵
        }↵
        else {↵
            push();↵
            l->set(L, R, x);↵
            r->set(L, R, x);↵
            val = l->val + r->val;↵
        }↵
    }↵
    void add(int L, int R, int x) {↵
        if (R <= lo || hi <= L) return;↵
        if (L <= lo && hi <= R) {↵
            if (mset != inf) mset += x;↵
            else madd += x;↵
            val += x * (hi - lo);↵
        }↵
        else {↵
            push();↵
            l->add(L, R, x);↵
            r->add(L, R, x);↵
            val = l->val + r->val;↵
        }↵
    }↵
    void push() {↵
        if (!l) {↵
            int mid = lo + (hi - lo) / 2;↵
            l = new Node(lo, mid); r = new Node(mid, hi);↵
        }↵
        if (mset != inf) {↵
            l->set(lo, hi, mset);↵
            r->set(lo, hi, mset);↵
            mset = inf;↵
        }↵
        else if (madd) {↵
            l->add(lo, hi, madd);↵
            r->add(lo, hi, madd);↵
            madd = 0;↵
        }↵
    }↵
};↵

void solve(int testcase) {↵
    int n; cin >> n;↵
    vi a(n); cin >> a;↵

    map<int, set<int>> pos;↵
    for (int i = 0; i < n; i++) {↵
        pos[a[i]].insert(i);↵
    }↵

    vi op(n);↵
    Node st(a, 0, n);↵
    Node st2(op, 0, n);↵

    int m; cin >> m;↵
    while (m--) {↵
        int clr; cin >> clr;↵
        if (pos.find(clr) == pos.end()) continue;↵

        auto &dq = pos[clr];↵
        if (dq.size() < 2) {↵
            pos.erase(clr);↵
            continue;↵
        }↵

        while (dq.size()) {↵
            int l = *dq.begin();↵
            if (st2.query(l, l + 1)) {↵
                dq.erase(dq.begin());↵
                continue;↵
            }↵
            break;↵
        }↵
        while (dq.size()) {↵
            int r = *prev(dq.end());↵
            if (st2.query(r, r + 1)) {↵
                dq.erase(prev(dq.end()));↵
                continue;↵
            }↵
            break;↵
        }↵
        if (dq.size() >= 2) {↵
            int l = *dq.begin();↵
            int r = *prev(dq.end());↵
            st.set(l, r + 1, a[l]);↵
            if (r > l + 1) st2.add(l + 1, r, 1);↵
        } else {↵
            pos.erase(clr);↵
        }↵
    }↵

    for (int i = 0; i < n; i++) {↵
        cout << st.query(i, i + 1) << " ";↵
    }↵
    pnl;↵
}↵

int32_t main() {↵
    using namespace chrono;↵
    ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);↵
    auto start = high_resolution_clock::now();↵
    int T = 1; // cin >> T;↵
    for (int t = 1; t <= T; t++) {↵
        solve(t);↵
    }↵
    auto end = high_resolution_clock::now();↵
    auto duration = duration_cast<milliseconds>(end - start);↵
#ifndef ONLINE_JUDGE↵
    cerr << "Time: " << duration.count() << " ms\n";↵
#endif↵
    return 0;↵
}↵
~~~~~↵


</spoiler>↵


Can anybody explain why `std::deque` has such high memory usage?

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en3 English Aarush 2024-10-20 19:14:39 0 (published)
en2 English Aarush 2024-10-20 19:12:36 8 Tiny change: 'std::dequeue` it use' -> 'std::deque` it use'
en1 English Aarush 2024-10-20 19:08:13 9509 Initial revision (saved to drafts)