이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
using ll = long long;
using ii = pair<int, int>;
using pll = pair<ll, ll>;
struct SegmentSegmentTree {
int lv;
vector<pll> d;
vector<ll> ins;
//1..n
SegmentSegmentTree(int n) {
lv = 2;
while(lv < n + 2)
lv *= 2;
d.resize(2 * lv + 3, {-1e18, 0});
ins.resize(2 * lv + 3);
for(int i = 1 ; i <= lv ; i++)
d[lv + i - 1].Y = i;
}
void initv(int i, ll x) {
d[lv + i - 1].X = x;
}
void process_init() {
for(int i = lv - 1 ; i >= 1 ; i--)
d[i] = max(d[2 * i], d[2 * i + 1]);
}
void insert(int a, int b, int l, int r, int w, ll x) {
if(a > r || b < l || l > r)
return ;
if(a <= l && r <= b) {
ins[w] += x;
d[w].X += x;
return;
}
insert(a, b, l, (l + r) / 2, 2 * w, x);
insert(a, b, (l + r) / 2 + 1, r, 2 * w + 1, x);
d[w] = max(d[2 * w], d[2 * w + 1]);
d[w].X += ins[w];
}
void insert(int a, int b, ll x) {
insert(a, b, 1, lv, 1, x);
}
pll query(int a, int b, int l, int r, int w) {
if(a > r || b < l || l > r)
return {-1e18, 0};
if(a <= l && r <= b)
return d[w];
pll p1 = query(a, b, l, (l + r) / 2, 2 * w);
pll p2 = query(a, b, (l + r) / 2 + 1, r, 2 * w + 1);
p1 = max(p1, p2);
p1.X += ins[w];
return p1;
}
pll query(int a, int b) {
return query(a, b, 1, lv, 1);
}
};
int n, q;
ll w;
vector<pll> G[100007];
ii E[100007];
ll ecost[100007];
int p[100007], sz[100007];
int in[100007], out[100007];
int rein[100007];
int nxt_num = 1;
int first[100007];
SegmentSegmentTree paths(100007);
SegmentSegmentTree subtrees(100007);
void dfs(int w) {
sz[w] = 1;
for(auto u : G[w]) {
if(u.X != p[w]) {
p[u.X] = w;
dfs(u.X);
sz[w] += sz[u.X];
}
}
}
ll dfs2(int w, ll dist) {
for(auto &u : G[w])
if(sz[u.X] > sz[G[w][0].X])
swap(u, G[w][0]);
in[w] = out[w] = nxt_num++;
rein[in[w]] = w;
subtrees.initv(in[w], dist);
ll maxdist = dist, maxall = dist;
for(auto u : G[w]) {
if(u == G[w][0])
first[u.X] = first[w];
else
first[u.X] = u.X;
if(u != G[w][0])
maxdist = max(maxdist, dfs2(u.X, dist + u.Y));
else
maxall = max(maxall, dfs2(u.X, dist + u.Y));
out[w] = out[u.X];
}
//~ cout << w << " " << maxdist << endl;
maxall = max(maxall, maxdist);
paths.initv(in[w], maxdist - 2LL * dist);
return maxall;
}
ll longest_path() {
auto q = subtrees.query(1, n);
int w = rein[q.Y], pre = 0;
ll dw = q.X;
//~ cout << dw << " " << w << endl;
ll res = 0;
while(w) {
if(!pre || first[pre] == first[w]) {
res = max(res, paths.query(in[first[w]], in[w]).X + dw);
//~ cout << in[first[w]] << " " << in[w] << " " << w << " " << res << " " << paths.query(in[first[w]], in[w]).X << endl;
pre = first[w];
w = p[first[w]];
} else {
ll pdist = subtrees.query(in[w], in[w]).X;
res = max(res, subtrees.query(in[w], in[pre] - 1).X + dw - 2LL * pdist);
//~ cout << w << " " << pre << " " << pdist << " " << dw << " " << res << endl;
res = max(res, subtrees.query(out[pre] + 1, out[w]).X + dw - 2LL * pdist);
//~ cout << w << " " << pre << " " << pdist << " " << dw << " " << res << endl;
pre = w;
w = p[w];
}
}
return res;
}
void change_edge(int e, ll x) {
//~ cout << e << " " << x << endl;
int w = E[e].X;
int u = E[e].Y;
if(in[w] > in[u])
swap(w, u);
ll delta = x - ecost[e];
ecost[e] = x;
paths.insert(in[u], out[u], -delta);
subtrees.insert(in[u], out[u], delta);
w = p[first[u]];
//~ cout << w << " " << u << endl;
while(w) {
//~ cout << w << endl;
ll actv = paths.query(in[w], in[w]).X;
ll pdist = subtrees.query(in[w], in[w]).X;
ll newv = subtrees.query(out[G[w][0].X] + 1, out[w]).X - 2LL * pdist;
//~ cout << actv << " " << newv << endl;
paths.insert(in[w], in[w], newv - actv);
w = p[first[w]];
}
}
int main() {
scanf("%d%d%lld", &n, &q, &w);
for(int i = 1 ; i < n ; i++) {
int a, b;
ll c;
scanf("%d%d%lld", &a, &b, &c);
G[a].emplace_back(b, c);
G[b].emplace_back(a, c);
ecost[i] = c;
E[i] = {a, b};
}
dfs(1);
for(int i = 1 ; i <= n ; i++) {
for(int j = 0 ; j < G[i].size() ; j++) {
if(G[i][j].X == p[i]) {
G[i].erase(G[i].begin() + j);
break;
}
}
}
first[1] = 1;
dfs2(1, 0);
subtrees.process_init();
paths.process_init();
//~ for(int i = 1 ; i <= n ; i++)
//~ cout << i << " "<< first[i] << endl;
//~ cout << longest_path() << endl;
//~ cout << paths.query(1, 1).X << endl;
//~ for(int i = 1 ; i <= n ; i++)
//~ cout << i << " " << in[i] << " " << paths.query(in[i], in[i]).X << " " << paths.query(in[i], in[i]).Y << endl;
ll last = 0;
while(q--) {
ll d, e;
scanf("%lld%lld", &d, &e);
d = (d + last) % (n - 1);
e = (e + last) % w;
change_edge(d + 1, e);
//~ for(int i = 1 ; i <= n ; i++)
//~ cout << i << " " << in[i] << " " << paths.query(in[i], in[i]).X << " " << paths.query(in[i], in[i]).Y << endl;
printf("%lld\n", last = longest_path());
}
return 0;
}
컴파일 시 표준 에러 (stderr) 메시지
diameter.cpp: In function 'int main()':
diameter.cpp:203:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for(int j = 0 ; j < G[i].size() ; j++) {
~~^~~~~~~~~~~~~
diameter.cpp:190:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
scanf("%d%d%lld", &n, &q, &w);
~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:194:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
scanf("%d%d%lld", &a, &b, &c);
~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:230:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
scanf("%lld%lld", &d, &e);
~~~~~^~~~~~~~~~~~~~~~~~~~
# | 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... |