关于ODT常数
  • 板块灌水区
  • 楼主mm1214
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/7/3 13:21
  • 上次更新2024/7/3 16:09:19
查看原帖
关于ODT常数
774258
mm1214楼主2024/7/3 13:21

rt,P2486是一道很简单的ODT题,可是我的ODTTLE30ptsTLE30pts,题解却AC了,求大佬帮我优化常数(悬3关)

My Code:

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#define int long long
#define pii pair<int , int>
#define pb emplace_back
#define mkp make_pair
#define ls (rt << 1)
#define rs (rt << 1 | 1)
#define mid (l + r >> 1)
using namespace std;
using namespace __gnu_pbds;
const int N = 100005 , inf = 1e18;
#define IT set<node>::iterator
int n , m , basis[N];
int fa[N] , dep[N] , dfn[N] , top[N] , son[N] , sz[N] , w[N] , timestamp;
vector <int> G[N];
struct ODT {
    struct node {
        int l , r; mutable int v;
        node (int _l = 0 , int _r = -1 , int _v = 0) :
            l(_l) , r(_r) , v(_v) {}
        bool operator < (const node &rhs) const {
            return l < rhs.l;
        }
        node operator + (const node &rhs) {
            return node(l ? l : rhs.l , rhs.r ? rhs.r : r , v + rhs.v - (r == rhs.l));
        }
    };
    set <node> odt;
    IT split(int pos) {
        IT it = --odt.upper_bound(node(pos));
        if (it->l == pos) return it;
        int l = it->l , r = it->r , v = it->v;
        odt.erase(it); odt.insert(node(l , pos - 1 , v));
        return odt.insert(node(pos , r , v)).first;
    }
    void assign(int l , int r , int v) {
        IT R = split(r + 1) , L = split(l);
        odt.erase(L , R);
        odt.insert(node(l , r , v));
    }
    node query(int l , int r) {
        IT R = split(r + 1) , L = split(l);
        node ans = node(0);
        for (; L != R; L++) {
            ans = ans + node(L->v , L->v , 1);
        }
        return ans;
    }
    void build() {
        int cnt = 1 , lst = w[1];
        for (int i = 2; i <= n; i++) {
            if (w[i] != lst) {
                odt.insert(node(i - cnt , i - 1 , lst));
                cnt = 1; lst = w[i];
            } else {
                ++cnt;
            }
        }
        odt.insert(node(n + 1 - cnt , n , lst));
        odt.insert(node(n + 1 , n + 3 , 0));
    }
} odt;
void dfs1(int u) {
    dep[u] = dep[fa[u]] + 1;
    for (auto v : G[u]) {
        if (v == fa[u]) continue;
        fa[v] = u; dfs1(v);
        sz[u] += sz[v];
        if (sz[v] > sz[son[u]]) son[u] = v;
    }
}
void dfs2(int u , int topu) {
    top[u] = topu; dfn[u] = ++timestamp;
    w[dfn[u]] = basis[u];
    if (son[u]) dfs2(son[u] , topu);
    for (auto v : G[u]) {
        if (v == fa[u] || v == son[u]) continue;
        dfs2(v , v);
    }
}
void path_assign(int x , int y , int z) {
    for (; top[x] != top[y]; x = fa[top[x]]) {
        if (dep[top[x]] < dep[top[y]]) swap(x , y);
        odt.assign(dfn[top[x]] , dfn[x] , z);
    }
    if (dep[x] > dep[y]) swap(x , y);
    odt.assign(dfn[x] , dfn[y] , z);
    return;
}
int path_query(int x , int y) {
    ODT::node L = ODT::node(0) , R = ODT::node(0);
    for (; top[x] != top[y];) {
        if (dep[top[x]] < dep[top[y]]) {
            R = odt.query(dfn[top[y]] , dfn[y]) + R;
            y = fa[top[y]];
        } else {
            L = odt.query(dfn[top[x]] , dfn[x]) + L;
            x = fa[top[x]];
        }
    }
    if (dep[x] > dep[y]) {
        L = odt.query(dfn[y] , dfn[x]) + L;
    } else {
        R = odt.query(dfn[x] , dfn[y]) + R;
    }
    swap(L.l , L.r);
    return (L + R).v;
}
void solve() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> basis[i];
    for (int i = 1 , x , y; i < n; i++) {
        cin >> x >> y; G[x].pb(y) , G[y].pb(x);
    }
    dfs1(1); dfs2(1 , 1);
    // for (int i = 1; i <= n; i++) odt.odt.insert(ODT::node(i , i , w[i]));
    // ODT常数优化------
    odt.build(); // !!!
    // ----------------
    char op;
    for (int i = 1 , x , y , z; i <= m; i++) {
        cin >> op >> x >> y;
        if (op == 'Q') {
            cout << path_query(x , y) << '\n';
        } else {
            cin >> z; path_assign(x , y , z);
        }
    }
    return;
}
signed main() {
    ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
    int T = 1;
    while(T--) solve();
    return 0;
}
2024/7/3 13:21
加载中...