关于线段树空间
查看原帖
关于线段树空间
141393
Dyd本人楼主2022/3/30 16:02

RT

蒻蒟打的是树剖 + 李超,由于懒就直接用 fill 把最小值 mn 填了:

#include <bits/stdc++.h>
#define STC static
#define fi first
#define se second
#define FF std::function
using LL = long long;
using PII = std::pair<int, int>;
const int N = 1e5 + 100;
const LL INF = 123456789123456789;
int n, m, ctl = 0, bid[N];
std::vector<PII> G[N];
LL dis[N];
struct Line
{
    int k;
    LL b;
    LL calc(int x){ return dis[bid[x]] * k + b; }
} li[N << 1];
namespace LC
{
    using std::max;
    using std::min;
    int id[N << 2];
    LL mn[N << 2];
    #define mid (l + r >> 1)
    #define lc (u << 1)
    #define rc (u << 1 | 1)
    bool judge(int a, int b, int x){ return li[a].calc(x) > li[b].calc(x); }
    void upd(int u, int l, int r, int ql, int qr, int d)
    {
        STC FF<void(int, int, int)> up = [&](int u, int l, int r)
        {
            mn[u] = min(mn[u], min(li[id[u]].calc(l), li[id[u]].calc(r)));
            mn[u] = min(mn[u], min(mn[lc], mn[rc])); 
        } ;
        if (l >= ql && r <= qr)
        {
            if (judge(id[u], d, mid)) std::swap(id[u], d);
            if (judge(id[u], d, l)) upd(lc, l, mid, ql, qr, d);
            if (judge(id[u], d, r)) upd(rc, mid + 1, r, ql, qr, d);
            return up(u, l, r); 
        }
        if (ql <= mid) upd(lc, l, mid, ql, qr, d);
        if (qr > mid) upd(rc, mid + 1, r, ql, qr, d);
        up(u, l, r);
    }
    LL ask(int u, int l, int r, int ql, int qr)
    {
        if (l >= ql && r <= qr) return mn[u];
        LL res = min(li[id[u]].calc(max(l, ql)), li[id[u]].calc(min(r, qr)));
        if (ql <= mid) res = min(res, ask(lc, l, mid, ql, qr));
        if (qr > mid) res = min(res, ask(rc, mid + 1, r, ql, qr));
        return res;
    }
    #undef mid
    #undef lc
    #undef rc
}
namespace TCS //TreeChainSegmentation
{
    
    int fa[N], top[N], id[N], cnt, dep[N], si[N], son[N];
    void prev()
    {
        FF<void(int, int, int, LL)> dfs1 = [&](int x, int f, int d, LL di)
        {
            fa[x] = f, dep[x] = d, dis[x] = di, si[x] = 1;
            for (PII e : G[x]) if (e.fi != f)
            {
                dfs1(e.fi, x, d + 1, di + e.se);
                si[x] += si[e.fi];
                if (si[e.fi] > si[son[x]]) son[x] = e.fi;
            }
        } ;
        FF<void(int, int)> dfs2 = [&](int x, int t)
        {
            top[x] = t, id[x] = ++cnt, bid[cnt] = x;
            if (!son[x]) return ;
            dfs2(son[x], t);
            for (PII e : G[x]) if (e.fi != fa[x] && e.fi != son[x]) dfs2(e.fi, e.fi);
        } ;
        dfs1(1, 0, 1, 0), dfs2(1, 1);
    }
    void change(int s, int t, int a, int b)
    {
        STC FF<int(int, int)> lca = [&](int x, int y)
        {
            while (top[x] != top[y]) dep[top[x]] > dep[top[y]] ? x = fa[top[x]] : y = fa[top[y]];
            return dep[x] > dep[y] ? y : x;
        } ; 
        STC FF<void(int, int, int)> modify = [&](int x, int y, int d)
        {
            while (top[x] != top[y]) LC::upd(1, 1, n, id[top[x]], id[x], d), x = fa[top[x]];
            LC::upd(1, 1, n, id[y], id[x], d);
        } ;
        int ff = lca(s, t);
        li[++ctl] = {-a, dis[s] * a + b}, modify(s, ff, ctl);
        li[++ctl] = {a, (dis[s] - (dis[ff] << 1)) * a + b}, modify(t, ff, ctl);
    }
    LL ask(int s, int t)
    {
        LL res = INF;
        while (top[s] != top[t])
        {
            if (dep[top[s]] < dep[top[t]]) std::swap(s, t);
            res = std::min(res, LC::ask(1, 1, n, id[top[s]], id[s])), s = fa[top[s]];
        }
        if (id[s] > id[t]) std::swap(s, t);
        return std::min(res, LC::ask(1, 1, n, id[s], id[t]));
    }
}
int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 1, u, v, w; i < n; ++i)
    {
        scanf("%d %d %d", &u, &v, &w);
        G[u].push_back({v, w}), G[v].push_back({u, w});
    }
    TCS::prev(), li[0] = {0, INF};
    std::fill(LC::mn, LC::mn + (N << 2), INF);
    for (int op, s, t, a, b; m--; )
    {
        scanf("%d %d %d", &op, &s, &t);
        if (op == 1)
        {
            scanf("%d %d", &a, &b);
            TCS::change(s, t, a, b);
        }
        else printf("%lld\n", TCS::ask(s, t));
    }
    return 0;
}

可以看到 2424 行的 LL mn[N << 2]121121 行的 std::fill(LC::mn, LC::mn + (N << 2), INF) ,然后交了, 95pts95pts

但把它们改成 LL mn[N << 4]std::fill(LC::mn, LC::mn + (N << 4), INF) (就是把空间开大)就 AC 了

那么蒻蒟我就很不李姐了,不是说好的线段树空间开四倍吗?为啥挂了?

求 dalao 解惑

2022/3/30 16:02
加载中...