这真的需要很大的空间吗?
  • 板块学术版
  • 楼主rainygame
  • 当前回复4
  • 已保存回复4
  • 发布时间2023/12/22 18:30
  • 上次更新2023/12/22 19:01:11
查看原帖
这真的需要很大的空间吗?
804607
rainygame楼主2023/12/22 18:30

题目:CF1797E

代码:

#include <bits/stdc++.h>
using namespace std;
#define MAXN 100001
#define MAXM 5000001

int n, m, opt, cnt, l, r;
int a[MAXN];
int phi[MAXM], dfn[MAXM], dfn2[MAXM];
int dep[MAXM], top[MAXM], siz[MAXM], son[MAXM], fa[MAXM];
list<int> pri;
list<int> e[MAXM];
bool np[MAXM];

void dfs1(int x){
    dep[x] = dep[fa[x]] + 1;
    siz[x] = 1;
    dfn[x] = ++cnt;
    dfn2[cnt] = x;
    for (auto i: e[x]){
        dfs1(i);
        siz[x] += siz[i];
        if (siz[son[x]] < siz[i]) son[x] = i;
    }
}

void dfs2(int x, int tp){
    top[x] = tp;
    if (son[x]) dfs2(son[x], tp);
    for (auto i: e[x]){
        if (i ^ son[x]) dfs2(i, i);
    }
}

int LCA(int x, int y){
    while (top[x] ^ top[y]){
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        x = fa[top[x]];
    }
    if (dep[x] < dep[y]) return x;
    return y;
}

void init(int n){
    phi[1] = 1;
    for (int i(2); i<=n; ++i){
        if (!np[i]){
            phi[i] = i-1;
            pri.push_back(i);
        }

        for (auto j: pri){
            if (i*j > n) break;
            np[i*j] = 1;
            if (i % j == 0){
                phi[i*j] = phi[i] * j;
                break;
            }
            phi[i*j] = phi[i] * phi[j];
        }
    }

    for (int i(2); i<=n; ++i){
        e[phi[i]].push_back(i);
        fa[i] = phi[i];
    }
    dfs1(1);
    dfs2(1, 1);
}

struct Node{
    int l, r;
    int maxn, minn;
    long long sum;
};

struct Seg{
    Node tree[MAXN];
    void push_up(int p){
        tree[p].minn = min(tree[p<<1].minn, tree[p<<1|1].minn);
        tree[p].maxn = max(tree[p<<1].maxn, tree[p<<1|1].maxn);
        tree[p].sum = tree[p<<1].sum + tree[p<<1|1].sum;
    }

    void build(int l, int r, int p){
        tree[p].l = l;
        tree[p].r = r;
        if (l == r){
            tree[p].maxn = tree[p].minn = dfn[a[l]];
            tree[p].sum = dep[a[l]];
            return;
        }

        int mid((l+r)>>1);
        build(l, mid, p<<1);
        build(mid+1, r, p<<1|1);
        push_up(p);
    }

    void modify(int L, int R, int p){
        if (tree[p].l == tree[p].r){
            tree[p].maxn = tree[p].minn = dfn[a[tree[p].l] = fa[a[tree[p].l]]];
            --tree[p].sum;
            return;
        }

        int mid((tree[p].l+tree[p].r)>>1);
        if (L <= mid && tree[p<<1].maxn > 1) modify(L, R, p<<1);
        if (R > mid && tree[p<<1|1].maxn > 1) modify(L, R, p<<1|1);
        push_up(p);
    }

    int query1(int L, int R, int p){
        if (tree[p].l >= L && tree[p].r <= R) return tree[p].minn;
        int mid((tree[p].l+tree[p].r)>>1), res(INT_MAX);
        if (L <= mid) res = min(res, query1(L, R, p<<1));
        if (R > mid) res = min(res, query1(L, R, p<<1|1));
        return res;
    }

    int query2(int L, int R, int p){
        if (tree[p].l >= L && tree[p].r <= R) return tree[p].maxn;
        int mid((tree[p].l+tree[p].r)>>1), res(0);
        if (L <= mid) res = max(res, query2(L, R, p<<1));
        if (R > mid) res = max(res, query2(L, R, p<<1|1));
        return res;
    }

    int query3(int L, int R, int p){
        if (tree[p].l >= L && tree[p].r <= R) return tree[p].sum;
        int mid((tree[p].l+tree[p].r)>>1), res(0);
        if (L <= mid) res += query3(L, R, p<<1);
        if (R > mid) res += query3(L, R, p<<1|1);
        return res;
    }
}tr;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    init(MAXM-1);

    cin >> n >> m;
    for (int i(1); i<=n; ++i) cin >> a[i];
    tr.build(1, n, 1);

    while (m--){
        cin >> opt >> l >> r;
        if (opt == 1) tr.modify(l, r, 1);
        else{
            int lca(LCA(dfn2[tr.query1(l, r, 1)], dfn2[tr.query2(l, r, 1)]));
            cout << tr.query3(l, r, 1)-(r-l+1)*dep[lca] << '\n';
        }
    }

    return 0;
}

在 Luogu IDE 中运行样例一直提示内存超限。

但是感觉题解和我的都差不多呀,他们就可以。

哪里出问题了?

2023/12/22 18:30
加载中...