rt,P2486是一道很简单的ODT题,可是我的ODTTLE30pts,题解却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;
}