結果
| 問題 |
No.235 めぐるはめぐる (5)
|
| コンテスト | |
| ユーザー |
norioc
|
| 提出日時 | 2025-11-15 08:17:07 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,461 ms / 10,000 ms |
| コード長 | 5,724 bytes |
| コンパイル時間 | 3,286 ms |
| コンパイル使用メモリ | 297,220 KB |
| 実行使用メモリ | 49,192 KB |
| 最終ジャッジ日時 | 2025-11-15 08:17:19 |
| 合計ジャッジ時間 | 9,781 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 3 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
static const long long MOD = 1e9 + 7;
// ===================== Data =====================
struct Data {
long long val; // 区間の和
long long coef; // 係数
Data(long long v = 0, long long c = 0) : val(v), coef(c) {}
};
Data op(const Data& a, const Data& b) {
return Data((a.val + b.val) % MOD,
(a.coef + b.coef) % MOD);
}
using Lazy = long long;
Data mapping(Lazy f, const Data& x) {
long long v = (x.val + x.coef * f) % MOD;
return Data(v, x.coef);
}
// 遅延合成
Lazy composition(Lazy f, Lazy g) {
return (f + g) % MOD;
}
// ===================== LazySegTree =====================
struct LazySegTree {
int n, log, size;
vector<Data> d;
vector<Lazy> lz;
LazySegTree(int _n, const vector<Data>& v) {
n = _n;
log = 0;
while ((1 << log) < n) log++;
size = 1 << log;
d.assign(2 * size, Data());
lz.assign(size, 0);
for (int i = 0; i < n; i++) d[size + i] = v[i];
for (int i = size - 1; i >= 1; i--) update(i);
}
void update(int k) {
d[k] = op(d[2*k], d[2*k+1]);
}
void all_apply(int k, Lazy f) {
d[k] = mapping(f, d[k]);
if (k < size) lz[k] = composition(f, lz[k]);
}
void push(int k) {
all_apply(2*k, lz[k]);
all_apply(2*k+1, lz[k]);
lz[k] = 0;
}
// 点更新
void set_val(int p, Data x) {
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
d[p] = x;
for (int i = 1; i <= log; i++) update(p >> i);
}
// 点取得
Data get(int p) {
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
return d[p];
}
// 区間 apply
void apply(int l, int r, Lazy f) {
if (l == r) return;
l += size;
r += size;
// push
for (int i = log; i >= 1; i--) {
if ((l >> i) << i != l) push(l >> i);
if ((r >> i) << i != r) push((r - 1) >> i);
}
int l2 = l, r2 = r;
while (l < r) {
if (l & 1) all_apply(l++, f);
if (r & 1) all_apply(--r, f);
l >>= 1; r >>= 1;
}
// update
l = l2; r = r2;
for (int i = 1; i <= log; i++) {
if ((l >> i) << i != l) update(l >> i);
if ((r >> i) << i != r) update((r - 1) >> i);
}
}
// 区間取得
Data prod(int l, int r) {
if (l == r) return Data();
l += size;
r += size;
for (int i = log; i >= 1; i--) {
if ((l >> i) << i != l) push(l >> i);
if ((r >> i) << i != r) push((r - 1) >> i);
}
Data sml, smr;
while (l < r) {
if (l & 1) sml = op(sml, d[l++]);
if (r & 1) smr = op(d[--r], smr);
l >>= 1; r >>= 1;
}
return op(sml, smr);
}
};
// ===================== HLD =====================
struct HLD {
int n;
vector<int> vid, inv, par, depth, sub, head, nex, type;
vector<vector<int>> adj;
HLD(int n, const vector<vector<int>>& g, int root=0)
: n(n), adj(g),
vid(n, -1), inv(n),
par(n, -1), depth(n),
sub(n, 1), head(n), nex(n, -1), type(n)
{
build(root);
}
void build(int root) {
dfs_sz(root);
int cur = 0;
dfs_hld(root, cur, root, 0);
}
void dfs_sz(int v) {
for (int& to : adj[v]) {
if (to == par[v]) continue;
par[to] = v;
depth[to] = depth[v] + 1;
dfs_sz(to);
sub[v] += sub[to];
if (nex[v] == -1 || sub[to] > sub[nex[v]]) nex[v] = to;
}
}
void dfs_hld(int v, int& cur, int h, int t) {
head[v] = h;
type[v] = t;
vid[v] = cur;
inv[cur] = v;
cur++;
if (nex[v] != -1)
dfs_hld(nex[v], cur, h, t);
for (int to : adj[v]) {
if (to == par[v] || to == nex[v]) continue;
dfs_hld(to, cur, to, t+1);
}
}
// u-v の頂点区間に [l, r] で callback
template<class F>
void foreach_nodes(int u, int v, F f) {
while (true) {
if (vid[u] > vid[v]) swap(u, v);
f(max(vid[head[v]], vid[u]), vid[v]);
if (head[u] != head[v])
v = par[head[v]];
else break;
}
}
};
// ===================== main =====================
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
vector<long long> S(N), C(N);
for (auto& x : S) cin >> x;
for (auto& x : C) cin >> x;
vector<vector<int>> adj(N);
for (int i = 0; i < N-1; i++) {
int a, b;
cin >> a >> b;
a--, b--;
adj[a].push_back(b);
adj[b].push_back(a);
}
HLD hld(N, adj, 0);
// HLD に合わせて並べる
vector<Data> xs(N);
for (int i = 0; i < N; i++) {
xs[hld.vid[i]] = Data(S[i], C[i]);
}
LazySegTree seg(N, xs);
int Q;
cin >> Q;
while (Q--) {
int t;
cin >> t;
if (t == 0) {
int x, y; long long z;
cin >> x >> y >> z;
x--, y--;
hld.foreach_nodes(x, y, [&](int l, int r) {
seg.apply(l, r+1, z);
});
} else {
int x, y;
cin >> x >> y;
x--, y--;
long long ans = 0;
hld.foreach_nodes(x, y, [&](int l, int r) {
ans = (ans + seg.prod(l, r+1).val) % MOD;
});
cout << ans << "\n";
}
}
return 0;
}
norioc