結果
問題 | No.235 めぐるはめぐる (5) |
ユーザー | Orisano |
提出日時 | 2017-11-22 00:30:50 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 1,283 ms / 10,000 ms |
コード長 | 7,040 bytes |
コンパイル時間 | 1,424 ms |
コンパイル使用メモリ | 86,488 KB |
実行使用メモリ | 33,860 KB |
最終ジャッジ日時 | 2024-05-04 18:42:08 |
合計ジャッジ時間 | 7,470 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1,283 ms
33,016 KB |
testcase_01 | AC | 783 ms
33,284 KB |
testcase_02 | AC | 1,197 ms
33,860 KB |
ソースコード
#include <algorithm> #include <functional> #include <vector> struct HLDecomposition { const int N; std::vector<std::vector<int>> tree; std::vector<int> cluster, par, depth, ord, head, offset; HLDecomposition(int N) : N(N), tree(N), cluster(N, -1), par(N, -1), depth(N), ord(N), offset(N) {} void add_edge(int u, int v) { tree[u].push_back(v); tree[v].push_back(u); } void build(int root = 0) { std::vector<int> Q; Q.reserve(N); Q.push_back(root); for (int i = 0; i < N; i++) { int u = Q[i]; for (int v : tree[u]) { if (par[u] == v) continue; par[v] = u; depth[v] = depth[u] + 1; Q.push_back(v); } } std::vector<int> subtree_size(N, 1); for (int i = N - 1; i > 0; i--) { subtree_size[par[Q[i]]] += subtree_size[Q[i]]; } std::vector<std::vector<int>> pathes; for (int u : Q) { if (cluster[u] == -1) { cluster[u] = pathes.size(); pathes.emplace_back(); } pathes[cluster[u]].push_back(u); int max_subsize = -1, selected = -1; for (int v : tree[u]) { if (par[u] == v) continue; if (max_subsize >= subtree_size[v]) continue; max_subsize = subtree_size[v]; selected = v; } if (selected != -1) cluster[selected] = cluster[u]; } int P = pathes.size(); head.resize(P + 1); for (int p = 0; p < P; p++) { int H = head[p]; int L = pathes[p].size(); head[p + 1] = H + L; for (int i = 0; i < L; i++) { int v = pathes[p][i]; offset[v] = i; ord[H + i] = v; } } } void for_each(int u, int v, std::function<void(int, int)> f) const { while (cluster[u] != cluster[v]) { if (depth[ord[head[cluster[u]]]] > depth[ord[head[cluster[v]]]]) std::swap(u, v); int h = head[cluster[v]]; f(h, h + offset[v] + 1); v = par[ord[h]]; } if (offset[u] > offset[v]) std::swap(u, v); f(head[cluster[u]] + offset[u], head[cluster[v]] + offset[v] + 1); } int lca(int u, int v) const { int x; for_each(u, v, [&](int l, int r) { x = ord[l]; }); return x; } std::vector<std::vector<int>> build_pathes() const { const int P = head.size() - 1; std::vector<std::vector<int>> pathes(P); for (int i = 0; i < P; i++) { pathes[i].reserve(head[i + 1] - head[i]); for (int j = head[i]; j < head[i + 1]; j++) { pathes[i].push_back(ord[j]); } } return pathes; } }; template <typename Monoid, typename Op> struct LazySegTree { using value_type = typename Monoid::value_type; using lazy_type = typename Op::value_type; using Index0 = int; const lazy_type none = Op::none(); const int N, H; std::vector<value_type> nodes; std::vector<lazy_type> lazy; LazySegTree(int size) : LazySegTree(size, 32 - __builtin_clz(size - 1)) {} LazySegTree(int size, int h) : LazySegTree(size, h, 1 << h) {} LazySegTree(int size, int h, int aligned) : N(aligned), H(h), nodes(aligned * 2, Monoid::empty()), lazy(aligned, none) {} inline void apply(int p, lazy_type value, int l, int r) { nodes[p] = Op::eval(nodes[p], value, l, r); if (p < N) lazy[p] = Op::merge(lazy[p], value); } inline void calc(int p, int l, int r) { auto x = Monoid::append(nodes[p << 1], nodes[p << 1 | 1]); if (lazy[p] == none) { nodes[p] = x; } else { nodes[p] = Op::eval(x, lazy[p], l, r); } } void build(Index0 l, Index0 r) { int k = 1; int R = r; for (l += N, r += N - 1; l > 1;) { if (!(r & 1)) R += k; l >>= 1, r >>= 1, k <<= 1; for (int i = r, j = R; i >= l; --i, j -= k) calc(i, j - k, j); } } void push(Index0 l, Index0 r) { int s = H, k = 1 << (H - 1); int L = 0; for (l += N, r += N - 1; s > 0; k >>= 1) { for (int i = l >> s, j = L; i <= r >> s; ++i, j += k) { j += k; if (lazy[i] != none) { apply(i << 1, lazy[i], j - k, j); apply(i << 1 | 1, lazy[i], j, j + k); lazy[i] = none; } } --s; if ((l >> s) & 1) L += k; } } void exec(Index0 l, Index0 r, lazy_type value) { if (value == none) return; int L = l, R = r, k = 1; int i = l, j = r; push(L, L + 1); push(R - 1, R); for (l += N, r += N; l < r; l >>= 1, r >>= 1, k <<= 1) { if (l & 1) { apply(l++, value, i, i + k); i += k; } if (r & 1) { apply(--r, value, j - k, j); j -= k; } } build(L, L + 1); build(R - 1, R); } value_type query(Index0 l, Index0 r) { push(l, l + 1); push(r - 1, r); value_type x = Monoid::empty(); for (l += N, r += N; l < r; l >>= 1, r >>= 1) { if (l & 1) x = Monoid::append(x, nodes[l++]); if (r & 1) x = Monoid::append(x, nodes[--r]); } return x; } }; #include <cstdio> #define mygc(c) (c) = getchar_unlocked() #define mypc(c) putchar_unlocked(c) // clang-format off template<typename T=int>inline T rd(){T x=0,m=0,k;for(;;){mygc(k);if(k=='-'){m=1;break;}if('0'<=k&&k<='9'){x=k-'0';break;}}for(;;){mygc(k);if(k<'0'||'9'<k)break;x=x*10+k-'0';}if(m)x=-x;return x;} template<typename T=int>inline void wr(T x,char c='\n'){int s=0,m=0;char b[32];if(x<0)m=1,x=-x;for(;x;x/=10)b[s++]=x%10;if(!s)b[s++]=0;if(m)mypc('-');for(;s--;)mypc(b[s]+'0');mypc(c);} // clang-format on using ll = long long; const unsigned long long MOD = 1e9 + 7; inline ll mod_add(ll x, ll y) { x += y; if (x > MOD) x -= MOD; return x; } inline ll mod_sub(ll x, ll y) { x -= y; if (x < 0) x += MOD; return x; } inline ll mod_mul(ll x, ll y) { return x * y % MOD; } struct Sum { using value_type = ll; static ll empty() { return 0; } static ll append(ll x, ll y) { return mod_add(x, y); } }; std::vector<ll> ssum, csum; struct Add { using value_type = ll; static ll none() { return 0; } static ll eval(ll x, ll v, int l, int r) { return mod_add(x, mod_mul(v, mod_sub(csum[r], csum[l]))); } static ll merge(ll x, ll y) { return mod_add(x, y); } }; int main() { int N = rd(); std::vector<ll> S(N); for (int i = 0; i < N; i++) S[i] = rd(); std::vector<ll> C(N); for (int i = 0; i < N; i++) C[i] = rd(); HLDecomposition hl(N); for (int i = 0; i < N - 1; i++) { int A = rd() - 1, B = rd() - 1; hl.add_edge(A, B); } hl.build(); LazySegTree<Sum, Add> seg(N); ssum.resize(N + 1); csum.resize(N + 1); for (int i = 0; i < N; i++) { ssum[i + 1] = mod_add(ssum[i], S[hl.ord[i]]); csum[i + 1] = mod_add(csum[i], C[hl.ord[i]]); } int Q = rd(); for (int i = 0; i < Q; i++) { int t = rd(); int x = rd() - 1, y = rd() - 1; if (t) { ll ans = 0; hl.for_each(x, y, [&](int l, int r) { ans = mod_add(ans, mod_sub(ssum[r], ssum[l])); ans = mod_add(ans, seg.query(l, r)); }); wr(ans); } else { ll z = rd(); hl.for_each(x, y, [&](int l, int r) { seg.exec(l, r, z); }); } } return 0; }