結果
| 問題 |
No.3194 Do Optimize Your Solution
|
| コンテスト | |
| ユーザー |
noya2
|
| 提出日時 | 2025-06-23 03:12:50 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
(最新)
AC
(最初)
|
| 実行時間 | - |
| コード長 | 26,017 bytes |
| コンパイル時間 | 4,487 ms |
| コンパイル使用メモリ | 326,796 KB |
| 実行使用メモリ | 66,668 KB |
| 最終ジャッジ日時 | 2025-06-27 20:51:09 |
| 合計ジャッジ時間 | 31,142 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 16 TLE * 1 |
ソースコード
#line 1 "c.cpp"
#line 2 "/Users/noya2/Desktop/Noya2_library/template/template.hpp"
using namespace std;
#include<bits/stdc++.h>
#line 1 "/Users/noya2/Desktop/Noya2_library/template/inout_old.hpp"
namespace noya2 {
template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p){
os << p.first << " " << p.second;
return os;
}
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p){
is >> p.first >> p.second;
return is;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v){
int s = (int)v.size();
for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i];
return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v){
for (auto &x : v) is >> x;
return is;
}
void in() {}
template <typename T, class... U>
void in(T &t, U &...u){
cin >> t;
in(u...);
}
void out() { cout << "\n"; }
template <typename T, class... U, char sep = ' '>
void out(const T &t, const U &...u){
cout << t;
if (sizeof...(u)) cout << sep;
out(u...);
}
template<typename T>
void out(const vector<vector<T>> &vv){
int s = (int)vv.size();
for (int i = 0; i < s; i++) out(vv[i]);
}
struct IoSetup {
IoSetup(){
cin.tie(nullptr);
ios::sync_with_stdio(false);
cout << fixed << setprecision(15);
cerr << fixed << setprecision(7);
}
} iosetup_noya2;
} // namespace noya2
#line 1 "/Users/noya2/Desktop/Noya2_library/template/const.hpp"
namespace noya2{
const int iinf = 1'000'000'007;
const long long linf = 2'000'000'000'000'000'000LL;
const long long mod998 = 998244353;
const long long mod107 = 1000000007;
const long double pi = 3.14159265358979323;
const vector<int> dx = {0,1,0,-1,1,1,-1,-1};
const vector<int> dy = {1,0,-1,0,1,-1,-1,1};
const string ALP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string alp = "abcdefghijklmnopqrstuvwxyz";
const string NUM = "0123456789";
void yes(){ cout << "Yes\n"; }
void no(){ cout << "No\n"; }
void YES(){ cout << "YES\n"; }
void NO(){ cout << "NO\n"; }
void yn(bool t){ t ? yes() : no(); }
void YN(bool t){ t ? YES() : NO(); }
} // namespace noya2
#line 2 "/Users/noya2/Desktop/Noya2_library/template/utils.hpp"
#line 6 "/Users/noya2/Desktop/Noya2_library/template/utils.hpp"
namespace noya2{
unsigned long long inner_binary_gcd(unsigned long long a, unsigned long long b){
if (a == 0 || b == 0) return a + b;
int n = __builtin_ctzll(a); a >>= n;
int m = __builtin_ctzll(b); b >>= m;
while (a != b) {
int mm = __builtin_ctzll(a - b);
bool f = a > b;
unsigned long long c = f ? a : b;
b = f ? b : a;
a = (c - b) >> mm;
}
return a << std::min(n, m);
}
template<typename T> T gcd_fast(T a, T b){ return static_cast<T>(inner_binary_gcd(std::abs(a),std::abs(b))); }
long long sqrt_fast(long long n) {
if (n <= 0) return 0;
long long x = sqrt(n);
while ((x + 1) * (x + 1) <= n) x++;
while (x * x > n) x--;
return x;
}
template<typename T> T floor_div(const T n, const T d) {
assert(d != 0);
return n / d - static_cast<T>((n ^ d) < 0 && n % d != 0);
}
template<typename T> T ceil_div(const T n, const T d) {
assert(d != 0);
return n / d + static_cast<T>((n ^ d) >= 0 && n % d != 0);
}
template<typename T> void uniq(std::vector<T> &v){
std::sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
}
template <typename T, typename U> inline bool chmin(T &x, U y) { return (y < x) ? (x = y, true) : false; }
template <typename T, typename U> inline bool chmax(T &x, U y) { return (x < y) ? (x = y, true) : false; }
template<typename T> inline bool range(T l, T x, T r){ return l <= x && x < r; }
} // namespace noya2
#line 8 "/Users/noya2/Desktop/Noya2_library/template/template.hpp"
#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define repp(i,m,n) for (int i = (m); i < (int)(n); i++)
#define reb(i,n) for (int i = (int)(n-1); i >= 0; i--)
#define all(v) (v).begin(),(v).end()
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull = unsigned long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using pil = pair<int,ll>;
using pli = pair<ll,int>;
namespace noya2{
/* ~ (. _________ . /) */
}
using namespace noya2;
#line 3 "c.cpp"
#line 2 "fastio.hpp"
#line 4 "fastio.hpp"
namespace nachia{
struct CInStream{
private:
static const unsigned int INPUT_BUF_SIZE = 1 << 17;
unsigned int p = INPUT_BUF_SIZE;
static char Q[INPUT_BUF_SIZE];
public:
using MyType = CInStream;
char seekChar(){
if(p == INPUT_BUF_SIZE){
size_t len = fread(Q, 1, INPUT_BUF_SIZE, stdin);
if(len != INPUT_BUF_SIZE) Q[len] = '\0';
p = 0;
}
return Q[p];
}
void skipSpace(){ while(isspace(seekChar())) p++; }
private:
template<class T, int sp = 1>
T nextUInt(){
if constexpr (sp) skipSpace();
T buf = 0;
while(true){
char tmp = seekChar();
if('9' < tmp || tmp < '0') break;
buf = buf * 10 + (tmp - '0');
p++;
}
return buf;
}
public:
uint32_t nextU32(){ return nextUInt<uint32_t>(); }
int32_t nextI32(){
skipSpace();
if(seekChar() == '-'){
p++; return (int32_t)(-nextUInt<uint32_t, 0>());
}
return (int32_t)nextUInt<uint32_t, 0>();
}
uint64_t nextU64(){ return nextUInt<uint64_t>();}
int64_t nextI64(){
skipSpace();
if(seekChar() == '-'){
p++; return (int64_t)(-nextUInt<int64_t, 0>());
}
return (int64_t)nextUInt<int64_t, 0>();
}
template<class T>
T nextInt(){
skipSpace();
if(seekChar() == '-'){
p++;
return - nextUInt<T, 0>();
}
return nextUInt<T, 0>();
}
char nextChar(){ skipSpace(); char buf = seekChar(); p++; return buf; }
std::string nextToken(){
skipSpace();
std::string buf;
while(true){
char ch = seekChar();
if(isspace(ch) || ch == '\0') break;
buf.push_back(ch);
p++;
}
return buf;
}
MyType& operator>>(unsigned int& dest){ dest = nextU32(); return *this; }
MyType& operator>>(int& dest){ dest = nextI32(); return *this; }
MyType& operator>>(unsigned long& dest){ dest = nextU64(); return *this; }
MyType& operator>>(long& dest){ dest = nextI64(); return *this; }
MyType& operator>>(unsigned long long& dest){ dest = nextU64(); return *this; }
MyType& operator>>(long long& dest){ dest = nextI64(); return *this; }
MyType& operator>>(std::string& dest){ dest = nextToken(); return *this; }
MyType& operator>>(char& dest){ dest = nextChar(); return *this; }
} ncin;
struct FastOutputTable{
char LZ[1000][4] = {};
char NLZ[1000][4] = {};
constexpr FastOutputTable(){
using u32 = uint_fast32_t;
for(u32 d=0; d<1000; d++){
LZ[d][0] = ('0' + d / 100 % 10);
LZ[d][1] = ('0' + d / 10 % 10);
LZ[d][2] = ('0' + d / 1 % 10);
LZ[d][3] = '\0';
}
for(u32 d=0; d<1000; d++){
u32 i = 0;
if(d >= 100) NLZ[d][i++] = ('0' + d / 100 % 10);
if(d >= 10) NLZ[d][i++] = ('0' + d / 10 % 10);
if(d >= 1) NLZ[d][i++] = ('0' + d / 1 % 10);
NLZ[d][i++] = '\0';
}
}
};
struct COutStream{
private:
using u32 = uint32_t;
using u64 = uint64_t;
using MyType = COutStream;
static const u32 OUTPUT_BUF_SIZE = 1 << 17;
static char Q[OUTPUT_BUF_SIZE];
static constexpr FastOutputTable TB = FastOutputTable();
u32 p = 0;
static constexpr u32 P10(u32 d){ return d ? P10(d-1)*10 : 1; }
static constexpr u64 P10L(u32 d){ return d ? P10L(d-1)*10 : 1; }
template<class T, class U> static void Fil(T& m, U& l, U x){ m = l/x; l -= m*x; }
public:
void next_dig9(u32 x){
u32 y;
Fil(y, x, P10(6));
nextCstr(TB.LZ[y]);
Fil(y, x, P10(3));
nextCstr(TB.LZ[y]); nextCstr(TB.LZ[x]);
}
void nextChar(char c){
Q[p++] = c;
if(p == OUTPUT_BUF_SIZE){ fwrite(Q, p, 1, stdout); p = 0; }
}
void nextEoln(){ nextChar('\n'); }
void nextCstr(const char* s){ while(*s) nextChar(*(s++)); }
void nextU32(uint32_t x){
u32 y = 0;
if(x >= P10(9)){
Fil(y, x, P10(9));
nextCstr(TB.NLZ[y]); next_dig9(x);
}
else if(x >= P10(6)){
Fil(y, x, P10(6));
nextCstr(TB.NLZ[y]);
Fil(y, x, P10(3));
nextCstr(TB.LZ[y]); nextCstr(TB.LZ[x]);
}
else if(x >= P10(3)){
Fil(y, x, P10(3));
nextCstr(TB.NLZ[y]); nextCstr(TB.LZ[x]);
}
else if(x >= 1) nextCstr(TB.NLZ[x]);
else nextChar('0');
}
void nextI32(int32_t x){
if(x >= 0) nextU32(x);
else{ nextChar('-'); nextU32((u32)-x); }
}
void nextU64(uint64_t x){
u32 y = 0;
if(x >= P10L(18)){
Fil(y, x, P10L(18));
nextU32(y);
Fil(y, x, P10L(9));
next_dig9(y); next_dig9(x);
}
else if(x >= P10L(9)){
Fil(y, x, P10L(9));
nextU32(y); next_dig9(x);
}
else nextU32(x);
}
void nextI64(int64_t x){
if(x >= 0) nextU64(x);
else{ nextChar('-'); nextU64((u64)-x); }
}
template<class T>
void nextInt(T x){
if(x < 0){ nextChar('-'); x = -x; }
if(!(0 < x)){ nextChar('0'); return; }
std::string buf;
while(0 < x){
buf.push_back('0' + (int)(x % 10));
x /= 10;
}
for(int i=(int)buf.size()-1; i>=0; i--){
nextChar(buf[i]);
}
}
void writeToFile(bool flush = false){
fwrite(Q, p, 1, stdout);
if(flush) fflush(stdout);
p = 0;
}
COutStream(){ Q[0] = 0; }
~COutStream(){ writeToFile(); }
MyType& operator<<(unsigned int tg){ nextU32(tg); return *this; }
MyType& operator<<(unsigned long tg){ nextU64(tg); return *this; }
MyType& operator<<(unsigned long long tg){ nextU64(tg); return *this; }
MyType& operator<<(int tg){ nextI32(tg); return *this; }
MyType& operator<<(long tg){ nextI64(tg); return *this; }
MyType& operator<<(long long tg){ nextI64(tg); return *this; }
MyType& operator<<(const std::string& tg){ nextCstr(tg.c_str()); return *this; }
MyType& operator<<(const char* tg){ nextCstr(tg); return *this; }
MyType& operator<<(char tg){ nextChar(tg); return *this; }
} ncout;
char CInStream::Q[INPUT_BUF_SIZE];
char COutStream::Q[OUTPUT_BUF_SIZE];
} // namespace nachia
#line 5 "c.cpp"
struct fast_lca {
int n;
std::vector<int> down, dep;
std::vector<int> a, pre, suf;
std::vector<std::vector<int>> st;
static constexpr int LG = 4;
static constexpr int MASK = (1 << LG) - 1;
fast_lca () {}
fast_lca (const std::vector<int> &par) : n(par.size()), down(n), dep(n), a(n) {
assert(n >= 1);
// subtree size - 1
for (int i = n - 1; i >= 1; i--){
down[par[i]] += down[i] + 1;
}
// euler tour time
for (int i = 1; i < n; i++){
down[i] = std::exchange(down[par[i]], down[par[i]] - down[i] - 1);
dep[i] = dep[par[i]] + 1;
}
// build a, pre, suf
for (int i = 1; i < n; i++){
a[down[i] - 1] = par[i];
}
pre = suf = a;
for (int i = 1; i < n; i++){
if (i & MASK){
if (pre[i] > pre[i - 1]){
pre[i] = pre[i - 1];
}
}
}
for (int i = n - 1; i >= 1; i--){
if (i & MASK){
if (suf[i - 1] > suf[i]){
suf[i - 1] = suf[i];
}
}
}
// build st
int n2 = n >> LG;
int lg = (n2 <= 1 ? 1 : std::bit_width<uint32_t>(n2 - 1));
st.resize(lg);
st[0].resize(n2);
for (int i = 0; i < n2; i++){
st[0][i] = suf[i << LG];
}
for (int d = 0; d < lg - 1; d++){
int nsz = (int)(st[d].size()) - (1 << d);
st[d + 1].resize(nsz);
for (int i = 0; i < nsz; i++){
int x = st[d][i];
int y = st[d][i + (1 << d)];
st[d + 1][i] = (x < y ? x : y);
}
}
}
int st_prod(int l, int r) const {
if (l == r){
return std::numeric_limits<int>::max();
}
int k = std::bit_width<uint32_t>(r - l) - 1;
int x = st[k][l];
int y = st[k][r - (1 << k)];
return (x < y ? x : y);
}
int prod(int l, int r) const {
assert(l < r);
r--;
int x = l >> LG, y = r >> LG;
if (x < y){
int p1 = suf[l];
int p2 = st_prod(x + 1, y);
int p3 = pre[r];
return (p1 < p2 ? (p1 < p3 ? p1 : p3) : (p2 < p3 ? p2 : p3));
}
int ret = a[l];
for (int i = l + 1; i <= r; i++){
if (ret > a[i]){
ret = a[i];
}
}
return ret;
}
int lca(int u, int v) const {
if (u == v) return u;
u = down[u], v = down[v];
if (u > v) std::swap(u, v);
return prod(u, v);
}
uint dist(int u, int v) const {
int l = lca(u, v);
return dep[u] + dep[v] - 2 * dep[l];
}
};
#line 2 "/Users/noya2/Desktop/Noya2_library/data_structure/csr.hpp"
#line 4 "/Users/noya2/Desktop/Noya2_library/data_structure/csr.hpp"
#include<ranges>
#line 7 "/Users/noya2/Desktop/Noya2_library/data_structure/csr.hpp"
namespace noya2::internal {
template<class E>
struct csr {
csr () {}
csr (int _n) : n(_n) {}
csr (int _n, int m) : n(_n){
start.reserve(m);
elist.reserve(m);
}
// ACL style constructor (do not have to call build)
csr (int _n, const std::vector<std::pair<int,E>> &idx_elem) : n(_n), start(_n + 2), elist(idx_elem.size()) {
for (auto &[i, e] : idx_elem){
start[i + 2]++;
}
for (int i = 1; i < n; i++){
start[i + 2] += start[i + 1];
}
for (auto &[i, e] : idx_elem){
elist[start[i + 1]++] = e;
}
prepared = true;
}
int add(int idx, E elem){
int eid = start.size();
start.emplace_back(idx);
elist.emplace_back(elem);
return eid;
}
void build(){
if (prepared) return ;
int m = start.size();
std::vector<E> nelist(m);
std::vector<int> nstart(n + 2, 0);
for (int i = 0; i < m; i++){
nstart[start[i] + 2]++;
}
for (int i = 1; i < n; i++){
nstart[i + 2] += nstart[i + 1];
}
for (int i = 0; i < m; i++){
nelist[nstart[start[i] + 1]++] = elist[i];
}
swap(elist,nelist);
swap(start,nstart);
prepared = true;
}
const auto operator[](int idx) const {
return std::ranges::subrange(elist.begin()+start[idx],elist.begin()+start[idx+1]);
}
auto operator[](int idx){
return std::ranges::subrange(elist.begin()+start[idx],elist.begin()+start[idx+1]);
}
const auto operator()(int idx, int l, int r) const {
return std::ranges::subrange(elist.begin()+start[idx]+l,elist.begin()+start[idx]+r);
}
auto operator()(int idx, int l, int r){
return std::ranges::subrange(elist.begin()+start[idx]+l,elist.begin()+start[idx]+r);
}
size_t size() const {
return n;
}
int n;
std::vector<int> start;
std::vector<E> elist;
bool prepared = false;
};
} // namespace noya2::internal
#line 102 "c.cpp"
struct simple_tree_for_yuki {
internal::csr<int> g;
simple_tree_for_yuki (int n) : g(n, (n - 1)*2) {}
template<typename Stream>
void input_edges(Stream &inputter){
for (int i = 0; i < g.n - 1; i++){
int u, v; inputter >> u >> v;
u--, v--;
g.add(u, v);
g.add(v, u);
}
g.build();
}
const auto operator[](int v) const {
return g[v];
}
auto operator[](int v){
return g[v];
}
int size() const {
return g.n;
}
};
struct hld_tree_for_yuki {
int n, root;
std::vector<int> down, nxt, sub, tour;
fast_lca fl;
hld_tree_for_yuki (int _n) : n(_n), root(0), down(n), nxt(n), sub(n, 1), tour(n) {}
template<typename Stream>
void input_edges(Stream &inputter){
for (int i = 1; i < n; i++){
int u, v; inputter >> u >> v;
u--, v--;
down[u]++;
down[v]++;
nxt[u] ^= v;
nxt[v] ^= u;
}
build_from_edges();
}
uint depth(int v) const {
return fl.dep[down[v]];
}
uint dist(int u, int v) const {
return fl.dist(down[u], down[v]);
}
int leader(int v) const {
return nxt[v] < 0 ? v : nxt[v];
}
// down[v] : degree of v
// nxt[v] : xor prod of neighbor of v
void build_from_edges(){
// use tour as queue
int back = 0;
for (int u = 0; u < n; u++){
if (u != root && down[u] == 1){
tour[back++] = u;
}
}
for (int front = 0; front < n - 1; front++){
int u = tour[front];
down[u] = -1;
int v = nxt[u]; // parent of v
nxt[v] ^= u;
if (--down[v] == 1 && v != root){
tour[back++] = v;
}
}
// check : now, tour is reverse of topological order
tour.pop_back();
// check : now, down[*] <= 1
for (int u : tour){
int v = nxt[u];
// subtree size (initialized (1,1,...,1))
sub[v] += sub[u];
// heaviest subtree of its child
if (down[v] < sub[u]){
down[v] = sub[u];
}
}
for (int u : tour){
int v = nxt[u];
// whether u is not the top of heavy path
if (down[v] == sub[u]){
sub[u] = ~sub[u];
down[v] = ~down[v];
}
}
// after appearing v as u (or v == root),
// down[v] is the visiting time of euler tour
// nxt[v] is the lowest vertex of heavy path which contains v
// (if v itself, nxt[v] is ~(parent of v))
// sub[v] + down[v] is the light child's starting time of euler tour
// note : heavy child's visiting time of euler tour is (the time of its parent) + 1
sub[root] = ~down[root] + 1;
down[root] = 0;
nxt[root] = -1;
std::vector<int> par(n);
for (int u : tour | std::views::reverse){
int v = nxt[u];
int nsub = ~down[u] + 1;
// heavy child
if (sub[u] < 0){
down[u] = down[v] + 1;
nxt[u] = (nxt[v] < 0 ? v : nxt[v]);
}
// light child
else {
down[u] = down[v] + sub[v];
sub[v] += sub[u];
nxt[u] = ~v;
}
sub[u] = nsub;
par[down[u]] = down[v];
}
fl = fast_lca(par);
// tour is inverse permutation of down
tour.push_back(root);
for (int u = 0; u < n; u++){
tour[down[u]] = u;
}
}
};
#line 2 "/Users/noya2/Desktop/Noya2_library/tree/centroid_decomposition.hpp"
#line 4 "/Users/noya2/Desktop/Noya2_library/tree/centroid_decomposition.hpp"
namespace noya2 {
std::vector<int> centroid_decomposition(const auto &g){
int n = g.size();
if (n == 0){
return {};
}
std::vector<int> sub(n), order;
order.reserve(n);
auto subtree = [&](auto sfs, int v, int f) -> void {
sub[v] = 1;
for (int u : g[v]){
if (u == f) continue;
sfs(sfs, u, v);
sub[v] += sub[u];
}
};
subtree(subtree,0,-1);
auto fixed_root = [&](auto self, int root, int par, int cur_size) -> void {
auto dfs = [&](auto sfs, int v, int f, int sz) -> int {
int heavy = 0, child = -1;
for (int u : g[v]){
if (u == f) continue;
if (heavy < sub[u]){
heavy = sub[u];
child = u;
}
}
if (heavy > sz/2){
int ret = sfs(sfs, child, v, sz);
sub[v] -= ret;
return ret;
}
else {
order.emplace_back(v);
for (int u : g[v]){
if (u == f) continue;
self(self, u, v, sub[u]);
}
int ret = sub[v];
sub[v] = 0;
return ret;
}
};
while (cur_size > 0){
cur_size -= dfs(dfs, root, par, cur_size);
}
};
fixed_root(fixed_root, 0, -1, n);
return order;
}
} // namespace noya2
#line 234 "c.cpp"
void solve(){
using nachia::ncin, nachia::ncout;
int n; ncin >> n;
simple_tree_for_yuki a(n);
hld_tree_for_yuki b(n);
a.input_edges(ncin);
b.input_edges(ncin);
vector<int> spfensz(n);
rep(v,n){
int lv = b.leader(v);
chmax(spfensz[lv], b.down[v] - b.down[lv] + 1);
}
vector<array<ull,2>> spfenfront(n,array<ull,2>{});
vector<array<ull,4>> spfen(n,array<ull,4>{});
ull rootdepsum = 0, rootdistsum = 0;
auto apply_from_root = [&](int v, int dist, int sgn){
ull x = 2 * sgn, y = 2 * dist * sgn;
rootdepsum += x;
rootdistsum += y;
while (true){
int lv = b.leader(v);
int start = b.down[lv];
int sz = spfensz[lv];
int r = b.down[v] + 1 - start;
int memor = r;
r++;
while (r <= sz){
int id = r - 1 + start;
spfen[id][0] += x * memor;
spfen[id][1] += -x;
spfen[id][2] += y * memor;
spfen[id][3] += -y;
r += r & -r;
}
spfenfront[start][0] += x;
spfenfront[start][1] += y;
if (lv == 0) break;
v = ~b.nxt[lv];
}
};
auto prod_from_root = [&](int v, int dist){
ull depsum = -rootdepsum, distsum = -rootdistsum;
while (true){
int lv = b.leader(v);
int start = b.down[lv];
int r = b.down[v] + 1 - start;
int memor = r;
array<ull,4> prod = {};
while (r > 0){
int id = r - 1 + start;
rep(i,4){
prod[i] += spfen[id][i];
}
r -= r & -r;
}
depsum += prod[0] + (prod[1] + spfenfront[start][0]) * memor;
distsum += prod[2] + (prod[3] + spfenfront[start][1]) * memor;
if (lv == 0) break;
v = ~b.nxt[lv];
}
return depsum * dist + distsum;
};
vector<bool> done(n,false);
ull ans = 0;
for (int ctr : centroid_decomposition(a)){
done[ctr] = true;
vector<pii> vds = {{ctr,0}};
vector<int> start = {0,1};
auto dfs = [&](auto sfs, int v, int f, int dist) -> void {
vds.emplace_back(v,dist);
for (int u : a[v]){
if (done[u]) continue;
if (u == f) continue;
sfs(sfs,u,v,dist+1);
}
};
for (int v : a[ctr]){
if (done[v]) continue;
dfs(dfs,v,ctr,1);
start.emplace_back(vds.size());
}
if (vds.size() < 100){
int csz = start.size() - 2;
rep(i,csz){
rep(j,i){
repp(ii,start[i+1],start[i+2]){
repp(jj,start[j+1],start[j+2]){
auto [u, ud] = vds[ii];
auto [v, vd] = vds[jj];
ans += (ud + vd) * b.dist(u,v);
}
}
}
repp(ii,start[i+1],start[i+2]){
auto [v, vd] = vds[ii];
ans += vd * b.dist(ctr,v);
}
}
continue;
}
// numof u, dist[u], dep[u], dist[u]*dep[u]
ull cnt = 0, distsum = 0, depsum = 0, prdsum = 0;
int csz = start.size() - 2;
// v : ctr
[&]{
// dist[u] * dep[u]
prdsum += 0;
// dist[u] * dep[v]
distsum += 0;
// dist[v] * dep[u]
depsum += b.depth(ctr);
// dist[v] * dep[v]
cnt += 1;
// dist[u] * -2dep[lca(u,v)]
// dist[v] * -2dep[lca(u,v)]
apply_from_root(ctr, 0, -1);
}();
auto proc1 = [&](int v, int dist){
// dist[u] * dep[u]
ans += prdsum;
// dist[u] * dep[v]
ans += distsum * b.depth(v);
// dist[v] * dep[u]
ans += dist * depsum;
// dist[v] * dep[v]
ans += (ull)dist * b.depth(v) * cnt;
// dist[u] * -2dep[lca(u,v)]
// dist[v] * -2dep[lca(u,v)]
ans += prod_from_root(v, dist);
};
auto proc2 = [&](int v, int dist){
// dist[u] * dep[u]
prdsum += (ull)dist * b.depth(v);
// dist[u] * dep[v]
distsum += dist;
// dist[v] * dep[u]
depsum += b.depth(v);
// dist[v] * dep[v]
cnt += 1;
// dist[u] * -2dep[lca(u,v)]
// dist[v] * -2dep[lca(u,v)]
apply_from_root(v, dist, -1);
};
auto proc3 = [&](int v, int dist){
// cancel of
// dist[u] * -2dep[lca(u,v)]
// dist[v] * -2dep[lca(u,v)]
apply_from_root(v, dist, 1);
};
rep(i,csz){
repp(j,start[i+1],start[i+2]){
auto [v, dist] = vds[j];
proc1(v,dist);
}
repp(j,start[i+1],start[i+2]){
auto [v, dist] = vds[j];
proc2(v,dist);
}
}
rep(i,csz){
repp(j,start[i+1],start[i+2]){
auto [v, dist] = vds[j];
proc3(v,dist);
}
}
[&]{
// cancel of
// dist[u] * -2dep[lca(u,v)]
// dist[v] * -2dep[lca(u,v)]
apply_from_root(ctr, 0, 1);
}();
}
ans *= 2;
ncout << ans << '\n';
}
int main(){
int t = 1; //in(t);
while (t--) { solve(); }
}
noya2