#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> ii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ii> vii;
typedef vector<vii> vvii;
typedef pair<double, double> dodo;
typedef pair<ll, ll> llp;
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)
int N;
vvi edges;
vi circle;
bool onCircle[200000] = {0};
vvi distantNodes;
vi distantDist;
vi distantSize;
int parent[200000];
bool vis[200000] = {0};
void fcircle(int x) {
vis[x] = true;
for (int i = 0; i < edges[x].size(); i++) {
int y = edges[x][i];
if (y == parent[x]) continue;
if (vis[y]) {
int q = x;
while (q != y) {
circle.pb(q);
q = parent[q];
}
circle.pb(y);
return;
}
parent[y] = x;
fcircle(y);
if (!circle.empty()) break;
}
}
int fdistance(int x) {
int ret = 0;
for (int i = 0; i < edges[x].size(); i++) {
int y = edges[x][i];
if (y == parent[x]) continue;
if (onCircle[y]) continue;
parent[y] = x;
ret = max(ret, 1 + fdistance(y));
}
return ret;
}
int fsize(int x, int dst) {
if (dst == 0) return 1;
int ret = 0;
for (int i = 0; i < edges[x].size(); i++) {
int y = edges[x][i];
if (y == parent[x]) continue;
if (onCircle[y]) continue;
parent[y] = x;
ret += fsize(y, dst-1);
}
return ret;
}
typedef struct NodeT {
int llim, rlim;
int value, valsz, up;
} Node;
const int segsz = 524288;
const int offset = segsz/2;
Node seg[segsz];
#define left(x) ((x)*2)
#define right(x) ((x)*2+1)
void seginit() {
for (int i = offset; i < segsz; i++) {
seg[i].llim = seg[i].rlim = i-offset;
seg[i].value = 0;
}
for (int i = offset-1; i > 0; i--) {
seg[i].llim = seg[left(i)].llim;
seg[i].rlim = seg[right(i)].rlim;
seg[i].value = 0;
}
}
// setPointWithSecondValue --> Can be used only before any normal update calls
void setPointWithSecondValue(int pos, int val1, int val2) {
pos += offset;
seg[pos].value = val1;
seg[pos].valsz = val2;
pos /= 2;
while (pos) {
int mx = max(seg[left(pos)].value, seg[right(pos)].value);
int sz = 0;
if (seg[left(pos)].value == mx) sz += seg[left(pos)].valsz;
if (seg[right(pos)].value == mx) sz += seg[right(pos)].valsz;
seg[pos].value = mx;
seg[pos].valsz = sz;
pos /= 2;
}
}
void push(int x) {
seg[x].value += seg[x].up;
if (x < offset) {
seg[left(x)].up += seg[x].up;
seg[right(x)].up += seg[x].up;
}
seg[x].up = 0;
}
ii get(int x, int l, int r) {
push(x);
int llim = seg[x].llim, rlim = seg[x].rlim;
int mid = (llim+rlim)/2;
if (l == llim && r == rlim) return mp(seg[x].value, seg[x].valsz);
else if (l > mid) return get(right(x), l, r);
else if (r <= mid) return get(left(x), l, r);
else {
ii a = get(left(x), l, mid);
ii b = get(right(x), mid+1, r);
int mx = max(a.first, b.first);
int sz = 0;
if (a.first == mx) sz += a.second;
if (b.first == mx) sz += b.second;
return mp(mx, sz);
}
}
void update(int x, int l, int r, int u) {
push(x);
int llim = seg[x].llim, rlim = seg[x].rlim;
int mid = (llim+rlim)/2;
if (l == llim && r == rlim) {
seg[x].up += u;
push(x);
return;
}
else if (l > mid) update(right(x), l, r, u);
else if (r <= mid) update(left(x), l, r, u);
else {
update(left(x), l, mid, u);
update(right(x), mid+1, r, u);
}
ii a = get(left(x), llim, mid);
ii b = get(right(x), mid+1, rlim);
int mx = max(a.first, b.first);
int sz = 0;
if (a.first == mx) sz += a.second;
if (b.first == mx) sz += b.second;
seg[x].value = mx;
seg[x].valsz = sz;
}
void debugpush(int x) {
push(x);
if (x < offset) {
debugpush(left(x));
debugpush(right(x));
} else {
seg[x].value += seg[x].up;
seg[x].up = 0;
}
}
ll dp[200000][2];
void dfs(int x) {
//dp[x][0] = dp[x][1] = 0;
ll mx = 0;
for (int i = 0; i < edges[x].size(); i++) {
int y = edges[x][i];
if (y == parent[x]) continue;
if (onCircle[y]) continue;
parent[y] = x;
dfs(y);
mx = max(mx, dp[y][0]);
}
ll presz = 0;
ll ans = 0;
for (int i = 0; i < edges[x].size(); i++) {
int y = edges[x][i];
if (y == parent[x]) continue;
if (onCircle[y]) continue;
if (dp[y][0] == mx) {
ans += presz * dp[y][1];
presz += dp[y][1];
}
}
dp[x][0] = mx+1;
dp[x][1] = ans;
}
llp solveTree(int st) {
parent[st] = -1;
dfs(st);
return mp(dp[st][0], dp[st][1]);
}
int main(int argc, char **argv) {
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> N; edges.resize(N);
for (int i = 0; i < N; i++) {
int a, b; cin >> a >> b; a--; b--;
edges[a].pb(b); edges[b].pb(a);
}
parent[0] = -1;
fcircle(0);
for (int i = 0; i < circle.size(); i++) onCircle[circle[i]] = true;
int circlen = circle.size();
distantDist.resize(circle.size());
distantSize.resize(circle.size());
for (int i = 0; i < circle.size(); i++) {
parent[circle[i]] = -1;
distantDist[i] = fdistance(circle[i]);
parent[circle[i]] = -1;
distantSize[i] = fsize(circle[i], distantDist[i]);
}
seginit();
for (int i = 0; i < circle.size(); i++) {
//update(1, i, i, distantDist[i] + min(i, circlen-i));
setPointWithSecondValue(i, distantDist[i] + min(i, circlen-i), distantSize[i]);
}
/*for (int i = 0; i < circle.size(); i++) {
cerr << circle[i] << " ";
} cerr << endl;
for (int i = 0; i < circle.size(); i++) {
//cerr << seg[offset+i].value << " ";
cerr << distantDist[i] << " ";
} cerr << endl;
for (int i = 0; i < circle.size(); i++) {
//cerr << seg[offset+i].value << " ";
cerr << distantSize[i] << " ";
} cerr << endl;
cerr << endl;*/
/*cerr << "the initial segment:" << endl;
for (int i = 0; i < circle.size(); i++) {
cerr << seg[offset+i].value << " ";
//cerr << distantDist[i] << " ";
} cerr << endl;*/
vector<ll> ans(circle.size());
vi selected(circle.size());
for (int i = 0; i < circle.size(); i++) {
/*cerr << "i is: " << i << " and this is how the segment currently is:" << endl;
debugpush(1); for (int i = 0; i < circle.size(); i++) {
cerr << seg[offset+i].value << " ";
} cerr << endl;*/
if (circlen % 2 == 0) {
int oppo = (i+circlen/2)%circlen;
int ex1 = i;
int ex2 = oppo;
if (ex1 > ex2) swap(ex1, ex2);
ii a = (ex1 != 0 ? get(1, 0, ex1-1) : mp(0, 0));
ii b = (ex2-ex1>1 ? get(1, ex1+1, ex2-1) : mp(0, 0));
ii c = (ex2 != circlen-1 ? get(1, ex2+1, circlen-1) : mp(0, 0));
int maxfst = max(a.first, max(b.first, c.first));
int sz = 0;
if (a.first == maxfst) sz += a.second;
if (b.first == maxfst) sz += b.second;
if (c.first == maxfst) sz += c.second;
ii o = get(1, oppo, oppo);
if (maxfst >= o.first) {
selected[i] = maxfst;
ans[i] += (ll)distantSize[i]*(ll)sz;
}
if (o.first >= maxfst) {
selected[i] = o.first;
ans[i] += (ll)distantSize[i]*(ll)o.second*(2ll);
}
} else { // circlen % 2 == 1
ii a = (i?get(1, 0, i-1):mp(0, 0));
ii b = (i!=circlen-1?get(1, i+1, circlen-1):mp(0, 0));
int maxfst = max(a.first, b.first);
int sz = 0;
if (a.first == maxfst) sz += a.second;
if (b.first == maxfst) sz += b.second;
selected[i] = maxfst;
ans[i] = (ll)distantSize[i]*(ll)sz;
}
selected[i] += distantDist[i];
/*cerr << "selected is set: " << selected[i] << endl;
cerr << "ans is set: " << ans[i] << endl;
cerr << endl;*/
if (circlen % 2 == 0) {
update(1, 0, circlen-1, 1);
int l = i+1, r = i+circlen/2;
if (r < circlen) {
update(1, l, r, -2);
} else if (l >= circlen) {
l -= circlen, r -= circlen;
update(1, l, r, -2);
} else {
update(1, l, circlen-1, -2);
r -= circlen;
update(1, 0, r, -2);
}
} else { // circlen % 2 == 1
update(1, 0, circlen-1, 1);
int l = i+1, r = i+circlen/2;
if (r < circlen) {
update(1, l, r, -2);
} else if (l >= circlen) {
l -= circlen, r -= circlen;
update(1, l, r, -2);
} else {
update(1, l, circlen-1, -2);
r -= circlen;
update(1, 0, r, -2);
}
int x = i+circlen/2+1;
if (x >= circlen) x -= circlen;
update(1, x, x, -1);
}
}
/*cerr << "the last of the segment:" << endl;
debugpush(1); for (int i = 0; i < circle.size(); i++) {
cerr << seg[offset+i].value << " ";
} cerr << endl;*/
int mxs = *(max_element(selected.begin(), selected.end()));
ll answer = 0;
for (int i = 0; i < circle.size(); i++) if (selected[i] == mxs) answer += ans[i];
answer /= 2;
/*for (int i = 0; i < circle.size(); i++) {
cerr << selected[i] << " ";
} cerr << endl;
for (int i = 0; i < circle.size(); i++) {
cerr << ans[i] << " ";
} cerr << endl;*/
// don't forget to check the furthest pairs inside one circle piece
for (int i = 0; i < circle.size(); i++) {
onCircle[circle[i]] = false;
llp res = solveTree(circle[i]);
if (res.first > mxs) {
mxs = res.first;
answer = res.second;
} else if (res.first == mxs) {
answer += res.second;
}
onCircle[circle[i]] = true;
}
cout << answer << endl;
return 0;
}
Compilation message
shymbulak.cpp: In function 'void fcircle(int)':
shymbulak.cpp:28:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 0; i < edges[x].size(); i++) {
~~^~~~~~~~~~~~~~~~~
shymbulak.cpp: In function 'int fdistance(int)':
shymbulak.cpp:48:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 0; i < edges[x].size(); i++) {
~~^~~~~~~~~~~~~~~~~
shymbulak.cpp: In function 'int fsize(int, int)':
shymbulak.cpp:60:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 0; i < edges[x].size(); i++) {
~~^~~~~~~~~~~~~~~~~
shymbulak.cpp: In function 'void dfs(int)':
shymbulak.cpp:170:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 0; i < edges[x].size(); i++) {
~~^~~~~~~~~~~~~~~~~
shymbulak.cpp:180:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 0; i < edges[x].size(); i++) {
~~^~~~~~~~~~~~~~~~~
shymbulak.cpp: In function 'int main(int, char**)':
shymbulak.cpp:210:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 0; i < circle.size(); i++) onCircle[circle[i]] = true;
~~^~~~~~~~~~~~~~~
shymbulak.cpp:215:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 0; i < circle.size(); i++) {
~~^~~~~~~~~~~~~~~
shymbulak.cpp:224:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 0; i < circle.size(); i++) {
~~^~~~~~~~~~~~~~~
shymbulak.cpp:250:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 0; i < circle.size(); i++) {
~~^~~~~~~~~~~~~~~
shymbulak.cpp:335:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 0; i < circle.size(); i++) if (selected[i] == mxs) answer += ans[i];
~~^~~~~~~~~~~~~~~
shymbulak.cpp:347:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 0; i < circle.size(); i++) {
~~^~~~~~~~~~~~~~~
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
10 ms |
10616 KB |
Output is correct |
2 |
Incorrect |
10 ms |
10724 KB |
Output isn't correct |
3 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
17 ms |
10800 KB |
Output is correct |
2 |
Incorrect |
11 ms |
10800 KB |
Output isn't correct |
3 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Incorrect |
154 ms |
17876 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |