結果
問題 |
No.2342 Triple Tree Query (Hard)
|
ユーザー |
|
提出日時 | 2024-11-28 15:31:01 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 3,226 ms / 10,000 ms |
コード長 | 6,902 bytes |
コンパイル時間 | 1,665 ms |
コンパイル使用メモリ | 101,524 KB |
最終ジャッジ日時 | 2025-02-25 06:21:48 |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 36 |
ソースコード
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <tuple> using namespace std; using i32 = int; using i64 = long long; using u32 = unsigned int; using u64 = unsigned long long; template<typename T> using vec = vector<T>; using pii = pair<u32, u32>; const u32 P = 998244353; struct mint { u32 val; mint(): val() { } mint(u32 x): val(x) { } mint &operator+=(mint t) { val += t.val; if (val >= P) val -= P; return *this; } mint &operator-=(mint t) { if (val < t.val) val += P; val -= t.val; return *this; } mint &operator*=(mint t) { val = (u64)val * t.val % P; return *this; } friend mint operator+(mint a, mint b) { return a += b; } friend mint operator-(mint a, mint b) { return a -= b; } friend mint operator*(mint a, mint b) { return a *= b; } mint pow(u32 y) { u64 res = 1, x = val; for (; y; y >>= 1) { if (y & 1) res = res * x % P; x = x * x % P; } return mint(res); } mint inv() { return pow(P - 2); } friend bool operator==(mint a, mint b) { return a.val == b.val; } }; bool pairle(const pii &x, const pii &y) { return x.first <= y.first && x.second <= y.second; } pii pairmin(const pii &x, const pii &y) { return {min(x.first, y.first), min(x.second, y.second)}; } pii pairmax(const pii &x, const pii &y) { return {max(x.first, y.first), max(x.second, y.second)}; } template<typename M> struct KDTree { using A = typename M::S; u32 n; vec<u32> rnk; struct Node { pii sp, ep; Node(): sp(), ep() { } Node(const pii &a): sp(a), ep(a) { } }; vec<A> t; vec<Node> d; KDTree(u32 _n, const vec<pii> &p): n(_n), rnk(n) { u32 m = 1; while (m < n) m = m * 2; t.resize(m * 2, M::un()); d.resize(m * 2); vec<u32> idx(n); for (u32 i = 0; i < n; i++) idx[i] = i; build<0>(p, idx, 0, n, 1); } template<u32 D> void build(const vec<pii> &p, vec<u32> &idx, u32 l, u32 r, u32 x) { if (l + 1 == r) { u32 id = idx[l]; d[x] = p[id]; rnk[id] = l; return ; } u32 mid = (l + r) >> 1; nth_element(idx.data() + l, idx.data() + mid, idx.data() + r, [&](u32 x, u32 y) {return std::get<D>(p[x]) < std::get<D>(p[y]);}); build<!D>(p, idx, l, mid, x * 2); build<!D>(p, idx, mid, r, x * 2 + 1); d[x].sp = pairmin(d[x * 2].sp, d[x * 2 + 1].sp); d[x].ep = pairmax(d[x * 2].ep, d[x * 2 + 1].ep); } void push_down(u32 x) { if (t[x] != M::un()) { M::oop(t[x * 2], t[x]); M::oop(t[x * 2 + 1], t[x]); t[x] = M::un(); } } void apply(const pii &st, const pii &ed, const A &a) { apply_rec(st, ed, a, 0, n, 1); } A get(u32 x) { return get_rec(rnk[x], 0, n, 1); } void apply_rec(const pii &st, const pii &ed, const A &a, u32 l, u32 r, u32 x) { if (pairle(st, d[x].sp) && pairle(d[x].ep, ed)) { M::oop(t[x], a); return ; } if (!pairle(st, d[x].ep) || !pairle(d[x].sp, ed)) return ; u32 mid = (l + r) >> 1; push_down(x); apply_rec(st, ed, a, l, mid, x * 2); apply_rec(st, ed, a, mid, r, x * 2 + 1); } A get_rec(u32 p, u32 l, u32 r, u32 x) { if (l + 1 == r) return t[x]; u32 mid = (l + r) >> 1; push_down(x); if (p < mid) return get_rec(p, l, mid, x * 2); return get_rec(p, mid, r, x * 2 + 1); } }; struct MonoidAffine { using S = pair<mint, mint>; static void oop(S &a, const S &b) { a.first *= b.first; (a.second *= b.first) += b.second; } static S un() { return {1, 0}; } }; signed main() { // freopen("tour.in", "r", stdin); // freopen("tour.out", "w", stdout); ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); u32 n, q; cin >> n >> q; vec<vec<u32>> g(n); for (u32 i = 1, u, v; i < n; i++) { cin >> u >> v; --u, --v; g[u].emplace_back(v); g[v].emplace_back(u); } vec<mint> a(n); for (u32 i = 0, x; i < n; i++) { cin >> x; a[i] = x; } vec<u32> dfn(n), rnk(n), dep(n), fa(n), dfnr(n), top(n), son(n, -1); u32 dfnn = 0; [&, dfs = [&](auto &&f, u32 x) -> void { dfn[x] = 1; for (u32 v: g[x]) if (v != fa[x]) { fa[v] = x; dep[v] = dep[x] + 1; f(f, v); dfn[x] += dfn[v]; if (son[x] == -1u || dfn[v] > dfn[son[x]]) son[x] = v; } }](){dfs(dfs, 0);}(); [&, dfs = [&](auto &&f, u32 x) -> void { dfn[x] = dfnn; rnk[dfnn++] = x; if (son[x] != -1u) { top[son[x]] = top[x]; f(f, son[x]); } for (u32 v: g[x]) if (v != fa[x] && v != son[x]) { top[v] = v; f(f, v); } dfnr[x] = dfnn - 1; }](){dfs(dfs, 0);}(); vec<pii> initp(n); for (u32 i = 0; i < n; i++) initp[i] = {dfn[i], dep[i]}; KDTree<MonoidAffine> t(n, initp); while (q--) { u32 op; cin >> op; if (op == 1) { u32 x; cin >> x; --x; auto xx = t.get(x); cout << (xx.first * a[x] + xx.second).val << '\n'; } else if (op == 4) { u32 x, y, k, b; cin >> x >> y >> k >> b; --x, --y; pair<mint, mint> val(k, b); while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); t.apply({dfn[top[x]], 0}, {dfn[x], n}, val); x = fa[top[x]]; } if (dep[x] > dep[y]) swap(x, y); t.apply({dfn[x], 0}, {dfn[y], n}, val); } else if (op == 3) { u32 x, k, b; cin >> x >> k >> b; --x; t.apply({dfn[x], 0}, {dfnr[x], n}, {k, b}); } else { u32 x, r, k, b; cin >> x >> r >> k >> b; --x; mint kk(mint(k).inv()); pair<mint, mint> val(k, b), ival(kk, mint(0) - kk * b); t.apply({dfn[x], dep[x]}, {dfnr[x], dep[x] + r}, val); while (r-- && x != 0) { if (r >= 1 && k != 0) { t.apply({dfn[x], dep[x]}, {dfnr[x], dep[x] + r - 1}, ival); } x = fa[x]; t.apply({dfn[x], dep[x]}, {dfnr[x], dep[x] + r}, val); } } } return 0; }