题解:P11163 [BalkanOI 2023] Weights
可爱猫猫题
令
现在我们要求的问题即是单点修改、求子树
然后就做完了,时间复杂度
贴个核心代码,省略了一些缺省源,应该不影响阅读。
const int mod = 998244353;
using mint = Source::mint<mod>;
int n, q, a[400010], dfn[400010], siz[400010], dep[400010], cnt;
mint pw[400010];
vector<int> e[400010];
struct pint {
int p, q;
pint(int a = 0, int b = 0) {
p = a;
q = b;
}
bool operator < (pint b) const {
int dp = p - b.p;
if (dp > 29) return false;
if (dp < -29) return true;
if (dp < 0) {
dp = -dp;
return pw[dp].x * 1LL * b.q > q;
}
return pw[dp].x * 1LL * q < b.q;
}
};
class segmentTree {
private :
pint tree[1600010];
inline int getLeft(int u) { return u << 1; }
inline int getRight(int u) { return u << 1 | 1; }
inline void pushUp(int u) { tree[u] = max(tree[getLeft(u)], tree[getRight(u)]); }
public :
void update(int u, int l, int r, int x, pint k) {
if (l == r) {
tree[u] = k;
return;
}
if (x <= (l + r) / 2) update(getLeft(u), l, (l + r) / 2, x, k);
else update(getRight(u), (l + r) / 2 + 1, r, x, k);
pushUp(u);
}
pint query(int u, int l, int r, int x, int y) {
if (x <= l && r <= y) return tree[u];
if (y <= (l + r) / 2) return query(getLeft(u), l, (l + r) / 2, x, y);
if (x > (l + r) / 2) return query(getRight(u), (l + r) / 2 + 1, r, x, y);
return max(query(getLeft(u), l, (l + r) / 2, x, y), query(getRight(u), (l + r) / 2 + 1, r, x, y));
}
}tree;
void DFS(int u, int p) {
siz[u] = 1;
dfn[u] = ++ cnt;
dep[u] = dep[p] + 1;
for (int v : e[u]) if (v != p) DFS(v, u), siz[u] += siz[v];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> q;
pw[0] = 1;
rep (i,1,n + n + 1) pw[i] = pw[i - 1] * 2;
rep (i,1,n) {
char op1, op2;
int u1, u2;
cin >> op1 >> u1 >> op2 >> u2;
if (op1 == 'W') u1 += n;
if (op2 == 'W') u2 += n;
e[i].emplace_back(u1);
e[i].emplace_back(u2);
}
rep (i,n + 1,n + n + 1) cin >> a[i];
DFS(1, 0);
rep (i,1,n + 1) tree.update(1, 1, n + n + 1, dfn[i + n], pint(dep[i + n], a[i + n]));
rep (i,1,q) {
int op;
cin >> op;
if (op == 1) {
int u, k;
cin >> u >> k;
u += n;
a[u] = k;
tree.update(1, 1, n + n + 1, dfn[u], pint(dep[u], a[u]));
} else {
int u;
cin >> u;
pint res = tree.query(1, 1, n + n + 1, dfn[u], dfn[u] + siz[u] - 1);
mint ans = pw[res.p] * res.q;
ans *= Source::quickPow<mod>(Source::quickPow<mod>(2, dep[u]), mod - 2);
cout << ans.x << '\n';
}
}
return 0;
}