TLE 70求调
查看原帖
TLE 70求调
235671
fireinice楼主2024/6/13 21:43

https://www.luogu.com.cn/record/162053244

感觉不是常数问题啊,后面几个全T飞了,但应该确实让每个点在每个块只遍历了一次吧.

或者给出用时大的数据也行,我以为一条链是极限但跑的挺快()

#include <algorithm>
#include <array>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <list>
#include <vector>
#define endl '\n'
using namespace std;
using ll = long long;
using pi2 = array<int, 2>;
using pi3 = array<int, 3>;
using pi4 = array<int, 4>;

const int N = 2e5 + 500, S = 500;
const ll inf = 1e18;
int B = 500;

int n, m, rt;
vector<pi2> G[N];
int fa[N], top[N], siz[N], son[N], dep[N], arr[N], dfn[N], dcnt;
ll wdep[N];
void dfs1(int u, int f) {
    fa[u] = f, dep[u] = dep[f] + 1, siz[u] = 1;
    for (pi2 e : G[u])
        if (e[0] != f)
            wdep[e[0]] = wdep[u] + e[1], dfs1(e[0], u), siz[u] += siz[e[0]], son[u] = siz[e[0]] > siz[son[u]] ? e[0] : son[u];
}
void dfs2(int u, int tp) {
    top[u] = tp, dfn[u] = ++dcnt, arr[dfn[u]] = u;
    if (son[u])
        dfs2(son[u], tp);
    for (pi2 e : G[u])
        if (e[0] != fa[u] && e[0] != son[u])
            dfs2(e[0], e[0]);
}
int inline const jump(int u, int d) {
    d = max(d, 1);
    while (dep[top[u]] > d)
        u = fa[top[u]];
    return arr[dfn[u] - (dep[u] - d)];
}
int a[N], has_jumped[N], to_jump[S];
ll res[S];
vector<int> keys[S];
bitset<N> vis[S];
int blk[N], lft[S];
int cc = 0;
void push_tag(int b, int l, int r) {
    r = min(r, lft[b + 1] - 1), l = max(l, lft[b]);
    for (int i = l; i <= r; i++) {
        cc++;
        if (to_jump[b] != has_jumped[i]) {
            a[i] = jump(a[i], dep[a[i]] - to_jump[b] + has_jumped[i]);
            if (!vis[b][a[i]])
                vis[b][a[i]] = true, keys[b].push_back(i);
        }
        has_jumped[i] = to_jump[b];
        res[b] = min(res[b], wdep[a[i]]);
    }
    if (res[b] == 0)
        keys[b].clear();
}
ll query_part(int b, int l, int r) {
    r = min(r, lft[b + 1] - 1), l = max(l, lft[b]);
    ll ans = inf;
    for (int i = l; i <= r; i++) {
        if (to_jump[b] != has_jumped[i])
            ans = min(ans, wdep[jump(a[i], dep[a[i]] - to_jump[b] + has_jumped[i])]);
        else
            ans = min(ans, wdep[a[i]]);
    }
    return ans;
}
void tag_block(int b) {
    to_jump[b]++;
    if (res[b] == 0)
        return;
    vector<int> new_keys;
    for (int i : keys[b]) {
        if (!fa[a[i]] || vis[b][fa[a[i]]])
            continue;
        vis[b][a[i]] = true, a[i] = fa[a[i]], has_jumped[i]++, res[b] = min(res[b], wdep[a[i]]), new_keys.push_back(i);
    }
    swap(keys[b], new_keys);
}
void jump_one(int i) {
    if (!fa[a[i]])
        return;
    a[i] = fa[a[i]], vis[blk[i]][a[i]] = true, res[blk[i]] = min(res[blk[i]], wdep[a[i]]);
}
void update(int l, int r) {
    int bl = blk[l], br = blk[r];
    push_tag(bl, l, r), bl != br && (push_tag(br, l, r), 0);
    if (br - bl <= 1) {
        for (int i = l; i <= r; i++)
            jump_one(i);
        return;
    }
    for (int i = bl + 1; i < br; i++)
        tag_block(i);
    for (int i = l; i < lft[bl + 1]; i++)
        jump_one(i);
    for (int i = lft[br]; i <= r; i++)
        jump_one(i);
}
ll query(int l, int r) {
    int bl = blk[l], br = blk[r];
    ll ans = query_part(bl, l, r);
    bl != br && (ans = min(ans, query_part(br, l, r)));
    if (br - bl <= 1) {
        return ans;
    }
    for (int i = bl + 1; i < br; i++)
        ans = min(ans, res[i]);
    return ans;
}
signed main() {
//    freopen("p.in", "r", stdin);
//    freopen("a.out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> m >> rt;
    for (int i = 1; i < n; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        G[u].push_back({v, w});
        G[v].push_back({u, w});
    }
    dfs1(rt, 0);
    dfs2(rt, rt);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
        blk[i] = (i - 1) / B + 1;
    for (int i = 1; i <= blk[n] + 1; i++)
        lft[i] = min((i - 1) * B + 1, n + 1);
    for (int i = 1; i <= blk[n]; i++) {
        res[i] = inf;
        for (int j = lft[i]; j < lft[i + 1]; j++) {
            keys[i].push_back(j), vis[i][a[j]] = true;
            res[i] = min(res[i], wdep[a[j]]);
        }
    }
    for (int i = 1; i <= m; i++) {
        int opt, l, r;
        cin >> opt >> l >> r;
        if (opt == 1)
            update(l, r);
        else
            cout << query(l, r) << endl;
    }
    cerr << cc << endl;
    return 0;
}
2024/6/13 21:43
加载中...