求助空间问题
查看原帖
求助空间问题
277792
Delov楼主2023/7/5 09:10

已知luogu是按照实际使用计算空间的,下面这份代码最大的几个点只用了 3×1063 \times 10^6 左右个线段树节点,但是所有测试点的内存用量都基本达到了静态内存总和,差的那一点大概是链表部分。我怀疑是哪里访问越界,但使用 Ubsan 或者直接将线段树节点开到 4×1064 \times 10^6 也没有任何问题,不过所有测试点内存仍然跑满,我确实找不到问题,求各位大佬帮忙看看

评测链接

格式化后代码

#include <bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
#define fre(x) freopen(#x ".in", "r", stdin), freopen(#x ".out", "w", stdout)
#define Rep(i, a, b) for (int i = a; i <= b; ++i)
#define Dwn(i, a, b) for (int i = a; i >= b; --i)
#define pii pair<int, int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;

const int maxn = 1e6 + 10, B = 1e6;

struct V1 {
    int val, pre, nxt;
} V[maxn * 2];
int tot;

struct List {
    int Head, Tail;
    void Init() {
        Head = ++tot, Tail = ++tot;
        V[Head].nxt = Tail, V[Tail].pre = Head;
    }
    void Push_back(int x) {
        ++tot;
        V[tot].val = x;
        V[tot].pre = V[Tail].pre, V[V[tot].pre].nxt = tot, V[tot].nxt = Tail, V[Tail].pre = tot;
    }
    void Merge(List &A) {
        V[V[Tail].pre].nxt = V[A.Head].nxt;
        V[V[A.Head].nxt].pre = V[Tail].pre;
        Tail = A.Tail;
    }
    void Pop_back() {
        int p = V[V[Tail].pre].pre;
        V[p].nxt = Tail, V[Tail].pre = p;
    }
    int Back() { return V[V[Tail].pre].val; }
} L[maxn];

int n, q;

pii operator-(const pii &x, const pii &y) { return pii(x.fir, x.sec - y.sec); }
pii operator+(const pii &x, const pii &y) {
    if (x.fir == y.fir)
        return pii(x.fir, x.sec + y.sec);
    return x.sec > y.sec ? x - y : y - x;
}

int root[maxn];
struct Seg {
#define LCH tr[rt].lch
#define RCH tr[rt].rch
    struct Tree {
        int lch, rch, siz;
        pii val;
    } tr[maxn * 30];
    int tot;
    void Pushup(int rt) {
        tr[rt].val = (tr[LCH].val + tr[RCH].val), tr[rt].siz = (tr[LCH].siz + tr[RCH].siz);
    }
    void Insert(int &rt, int l, int r, int x, int w) {
        if (!rt)
            rt = ++tot;
        if (l == r)
            return tr[rt].val.fir = x, tr[rt].val.sec += w, tr[rt].siz += w, void();
        int mid = (l + r) >> 1;
        if (x <= mid)
            Insert(LCH, l, mid, x, w);
        else
            Insert(RCH, mid + 1, r, x, w);
        Pushup(rt);
    }
    int Query(int rt, int l, int r, int x) {
        if (!rt)
            return 0;
        if (l == r)
            return tr[rt].val.sec;
        int mid = (l + r) >> 1;
        if (x <= mid)
            return Query(LCH, l, mid, x);
        else
            return Query(RCH, mid + 1, r, x);
    }
    int Merge(int x, int y, int l, int r) {
        if (!x || !y)
            return x | y;
        if (l == r)
            return tr[x].siz += tr[y].siz, tr[x].val.sec = tr[x].siz, x;
        int mid = (l + r) >> 1;
        tr[x].lch = Merge(tr[x].lch, tr[y].lch, l, mid);
        tr[x].rch = Merge(tr[x].rch, tr[y].rch, mid + 1, r);
        Pushup(x);
        return x;
    }
} T;

int a[maxn];

void solve() {
    cin >> n >> q;
    Rep(i, 1, n) {
        int len, x;
        cin >> len;
        L[i].Init();
        Rep(j, 1, len) cin >> x, L[i].Push_back(x), T.Insert(root[i], 1, B, x, 1);
    }
    while (q--) {
        int opt;
        cin >> opt;
        if (opt == 1) {
            int x, y;
            cin >> x >> y;
            L[x].Push_back(y);
            T.Insert(root[x], 1, B, y, 1);
        }
        if (opt == 2) {
            int x;
            cin >> x;
            T.Insert(root[x], 1, B, L[x].Back(), -1);
            L[x].Pop_back();
        }
        if (opt == 3) {
            int m;
            cin >> m;
            pii val;
            ll sum = 0, csum = 0;
            Rep(i, 1, m) cin >> a[i], val = (val + T.tr[root[a[i]]].val), sum += T.tr[root[a[i]]].siz;
            Rep(i, 1, m) csum += T.Query(root[a[i]], 1, B, val.fir);
            if ((csum << 1) > sum)
                cout << val.fir << "\n";
            else
                cout << -1 << "\n";
        }
        if (opt == 4) {
            int x, y, w;
            cin >> x >> y >> w;
            L[x].Merge(L[y]);
            L[w] = L[x];
            root[w] = T.Merge(root[x], root[y], 1, B);
        }
    }
    cerr << tot << "\n";
}

int main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    return solve(), 0;
}

2023/7/5 09:10
加载中...