이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
int n;
ll mod;
vector<int> adj[N];
int h[N];
// segment tree
void modify(vector<int>& seg, int l, int r, ll v) {
int m = seg.size()/2;
r = min(r, m-1);
for (l += m, r += m+1; l < r; l /= 2, r/=2) {
if (l&1) {
seg[l] = ((ll)seg[l] * v)%mod;
l++;
}
if (r&1) {
r--;
seg[r] = ((ll)seg[r] * v)%mod;
}
}
}
int query(vector<int>& seg, int p) {
int res = 1;
int m = seg.size()/2;
for (p += m; p > 0; p /= 2) res = ((ll)res * (ll)seg[p])%mod;
return res;
}
// centroid decompostion
int sz[N], rem[N];
vector<tuple<int,int,int>> centroids[N];
vector<vector<int>> seg[N];
int dfsSz(int u, int p=-1) {
sz[u] = 1;
for (int v : adj[u]) {
if (rem[v] || v == p) continue;
sz[u] += dfsSz(v, u);
}
return sz[u];
}
int dfsCent(int u, int p, int totSz) {
for (int v : adj[u])
if (!rem[v] && v != p)
if (sz[v]*2 > totSz)
return dfsCent(v, u, totSz);
return u;
}
int dfs(int u, int p, int cent, int sub, int d) {
centroids[u].push_back({cent, sub, d});
int depth = 0;
for (int v : adj[u])
if (!rem[v] && v != p)
depth = max(depth, dfs(v, u, cent, sub, d + 1));
return depth + 1;
}
void handleCentroid(int u) {
int sub = 0;
int depth = 0;
for (int v : adj[u]) {
if (rem[v]) continue;
int subDepth = dfs(v, u, u, sub, 1);
depth = max(depth, subDepth+1);
sub++;
}
depth = min(depth, 40);
seg[u].resize(depth+1);
centroids[u].push_back({u, -1, 0});
for (int i=0; i<=depth; i++)
seg[u][i].assign((sub+2)*2, 1);
}
void centroidDecomposition(int u) {
dfsSz(u);
int cent = dfsCent(u, -1, sz[u]);
handleCentroid(cent);
rem[cent] = 1;
for (int v : adj[cent])
if (!rem[v])
centroidDecomposition(v);
}
// operations
const int SQ = 7;
void updateVertex(int u, int r, int v) {
for (auto p : centroids[u]) {
int cent, sub, d;
tie(cent, sub, d) = p;
int mx = min<int>(r-d+1, seg[cent].size());
for (int i=0; i<mx; i++) {
while (i + SQ < mx) i += SQ;
if (sub == -1) {
modify(seg[cent][i], 0, 1e9, v);
} else {
modify(seg[cent][i], 0, sub-1, v);
modify(seg[cent][i], sub+1, 1e9, v);
}
}
}
}
int queryVertex(int u) {
int res = 1;
auto add = [&](int x) {
res = ((ll)res * (ll)x)%mod;
};
for (auto p : centroids[u]) {
int cent, sub, d;
tie(cent, sub, d) = p;
if (d < seg[cent].size())
add(query(seg[cent][d], sub));
for (int i=0; i<seg[cent].size(); i+=SQ)
if (i > d)
add(query(seg[cent][i], sub));
}
return res;
}
int main() {
// read graph
cin >> n >> mod;
for (int i=0; i<n-1; i++) {
int u, v; cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
// centroid decomposition
centroidDecomposition(1);
// initial state
for (int i=1; i<=n; i++) cin >> h[i];
for (int i=1; i<=n; i++) updateVertex(i, 0, h[i]);
// answer queries
int q; cin >> q;
while (q--) {
int t; cin >> t;
if (t == 1) {
int x, d, w; cin >> x >> d >> w;
updateVertex(x, d, w);
}
if (t == 2) {
int x; cin >> x;
cout << queryVertex(x) << endl;
}
}
}
컴파일 시 표준 에러 (stderr) 메시지
sprinkler.cpp: In function 'int queryVertex(int)':
sprinkler.cpp:114:11: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
114 | if (d < seg[cent].size())
| ~~^~~~~~~~~~~~~~~~~~
sprinkler.cpp:116:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
116 | for (int i=0; i<seg[cent].size(); i+=SQ)
| ~^~~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |