#include<bits/stdc++.h>
using namespace std;
#define int long long
#define vec vector
#define hmap unordered_map
const int MXN = 200'005;
int N, L;
int H[MXN];
bool is_centr[MXN*3];
set<int> tree[MXN*3];
int fi = MXN;
struct SegNode {
int mul = 1;
SegNode merge(SegNode other) {
//cerr << mul << ' ' << other.mul << '\n';
return {(mul * other.mul) % L};
}
};
// retrieves multiple of range mod L
// point update multiply one value
struct SegTree {
vec<SegNode> data;
int n;
SegTree(int in) {
n = 1;
while(n < in) n*=2;
data = vec<SegNode>(n*2);
}
void upd(int i, SegNode val) {
assert(i<n && i>=0);
i += n;
//cerr << "SZ: " << data.size() << ' ' << i << '\n';
data[i] = data[i].merge(val);
while(i > 1) {
i /= 2;
data[i] = data[i*2].merge(data[i*2+1]);
}
}
SegNode query_suffix(int l) {
assert(l<n && l >= 0);
return _query_suffix(l, n, 1, 0, n);
}
SegNode _query_suffix(int l, int r, int ti, int tl, int tr) {
if(l >= tr || r <= tl) {
return {};
}
if(l <= tl && r >= tr) {
return data[ti];
}
int tm = (tl + tr)/2;
return _query_suffix(l, r, ti*2, tl, tm).merge(_query_suffix(l, r, ti*2+1, tm, tr));
}
};
struct Centroid {
vec<SegTree> subtree_contrs{};
hmap<int, int> subtree_inds;
hmap<int, int> dists;
int root;
int size;
SegTree contr;
Centroid() : contr(1) {}
Centroid(int root, int size) : root(root), size(size), contr(size+1) {
is_centr[root] = true;
subtree_inds[root] = -1;
contr.upd(0, {H[root]});
dists[root] = 0;
int si = 0;
for(int u : tree[root]) {
if(is_centr[u]) continue;
subtree_contrs.push_back(SegTree(size+1));
dfs_init(u, root, 1, si++);
}
}
void dfs_init(int u, int p, int d, int s_i) {
if(is_centr[u]) return;
subtree_inds[u] = s_i;
dists[u] = d;
for(int v : tree[u]) {
if(v == p) continue;
dfs_init(v, u, d+(u<N), s_i);
}
}
};
Centroid centroids[MXN*3];
int centroid_pars[MXN*3];
int subtree_sz[MXN*3];
void comp_subtree_sz(int u, int p = -1) {
if(is_centr[u]) {
subtree_sz[u] = 0;
return;
}
subtree_sz[u] = 1;
for(int v : tree[u]) {
if(v == p) continue;
comp_subtree_sz(v, u);
subtree_sz[u] += subtree_sz[v];
}
}
int find_centroid(int u, int p, int mxsz) {
for(int v : tree[u]) {
if(v == p) continue;
if(subtree_sz[v] > mxsz) return find_centroid(v, u, mxsz);
}
return u;
}
void decompose(int u, int p = -1) {
if(is_centr[u]) return;
comp_subtree_sz(u);
int v = find_centroid(u, -1, subtree_sz[u]/2);
///cerr << "initializing centroid: " << v << '\n';
centroid_pars[v] = p;
centroids[v] = Centroid(v, subtree_sz[u]);
for(int w : tree[v]) {
decompose(w, v);
}
}
void make_tree_binary(int u, int p = -1, int ap = -1) {
tree[u].erase(ap);
if(p != -1) tree[u].insert(p);
if(tree[u].size() > 3) {
int r = fi++;
tree[r] = move(tree[u]);
tree[u] = {};
tree[u].insert(r);
tree[u].insert(p);
tree[r].erase(p);
int f = *tree[r].begin();
tree[r].erase(f);
tree[u].insert(f);
}
for(int v : tree[u]) {
if(v == p) continue;
make_tree_binary(v, u, (u<N) ? u : ap);
}
}
int32_t main() {
cin >> N >> L;
for(int i = 0; i<N-1; i++) {
int u, v;
cin >> u >> v;
u--;v--;
tree[u].insert(v);
tree[v].insert(u);
}
for(int i = 0; i<N; i++) {
cin >> H[i];
}
make_tree_binary(0);
decompose(0);
int Q;
cin >> Q;
while(Q--) {
//cerr << "HERE0" << '\n';
int t;
cin >> t;
if(t == 2) {
//cerr << "Here1" << '\n';
int u;
cin >> u;
u--;
int ans = 1;
int ci = u;
auto mult_ans = [&](int val) {
ans *= val;
ans %= L;
};
while(ci != -1) {
int d = centroids[ci].dists[u];
mult_ans(centroids[ci].contr.query_suffix(d).mul);
for(int i = 0; i<centroids[ci].subtree_contrs.size(); i++) {
if(centroids[ci].subtree_inds[u] != i) {
mult_ans(centroids[ci].subtree_contrs[i].query_suffix(d).mul);
}
}
ci = centroid_pars[ci];
//cerr << ci << '\n';
};
cout << ans << '\n';
}
else {
//cerr <<"HERE2" << '\n';
int u, d, w;
cin >> u >> d >> w;
u--;
centroids[u].contr.upd(min(centroids[u].contr.n-1, d), {w});
int ci = centroid_pars[u];
while(ci != -1) {
//cerr << "Cur Centroid: " << ci << '\n';
auto& c = centroids[ci];
int contr_d = d - c.dists[u];
if(contr_d < 0) {
ci = centroid_pars[ci];
continue;
}
auto& st = c.subtree_contrs[c.subtree_inds[u]];
contr_d = min(contr_d, st.n-1);
//cerr << st.n << '\n';
st.upd(contr_d, {w});
ci = centroid_pars[ci];
//cerr << ci << '\n';
}
}
}
}
Compilation message
sprinkler.cpp: In function 'int32_t main()':
sprinkler.cpp:198:21: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<SegTree>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
198 | for(int i = 0; i<centroids[ci].subtree_contrs.size(); i++) {
| ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
33 ms |
156508 KB |
Output is correct |
2 |
Correct |
34 ms |
156504 KB |
Output is correct |
3 |
Correct |
33 ms |
156504 KB |
Output is correct |
4 |
Correct |
37 ms |
158288 KB |
Output is correct |
5 |
Incorrect |
37 ms |
158428 KB |
Output isn't correct |
6 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
33 ms |
156500 KB |
Output is correct |
2 |
Runtime error |
323 ms |
374884 KB |
Execution killed with signal 11 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
33 ms |
156500 KB |
Output is correct |
2 |
Runtime error |
323 ms |
374884 KB |
Execution killed with signal 11 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
34 ms |
156508 KB |
Output is correct |
2 |
Execution timed out |
4107 ms |
736136 KB |
Time limit exceeded |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
33 ms |
156500 KB |
Output is correct |
2 |
Execution timed out |
4085 ms |
729444 KB |
Time limit exceeded |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
33 ms |
156508 KB |
Output is correct |
2 |
Correct |
34 ms |
156504 KB |
Output is correct |
3 |
Correct |
33 ms |
156504 KB |
Output is correct |
4 |
Correct |
37 ms |
158288 KB |
Output is correct |
5 |
Incorrect |
37 ms |
158428 KB |
Output isn't correct |
6 |
Halted |
0 ms |
0 KB |
- |