namespace sieve { int prime[N], pcnt; bool vis[N]; int mu[N]; voidprework(int n); } namespace dsu { ll dsuans; int fa[N], siz[N]; vector<pir> opt; voidinit(int n); voidmerge(int x, int y); voidcancel(); } namespace segment_tree { structnode { int siz; vector<int> t; } a[Q*4]; int lim; voidinsert(int ql, int qr, int id, int i = 1, int l = 0, int r = lim); voiddel(int ql, int qr, int i = 1, int l = 0, int r = lim); voidsolve(int v, int i = 1, int l = 0, int r = lim); } usingnamespace dsu; usingnamespace sieve; usingnamespace segment_tree;
structedge { int u, v, c; };
int n, q; edge e[N]; int last[N]; int lt[N], rt[N]; vector<int> g[N]; ll ans[N], d[N];
intmain() { cin >> n; sieve::prework(1e6); for(int i = 1; i < n; i++) { cin >> e[i].u >> e[i].v >> e[i].c; last[i] = i; } cin >> q; for(int i = 1; i <= q; i++) { int id, val; cin >> id >> val; rt[last[id]] = i-1; e[n+i-1] = e[last[id]]; e[n+i-1].c = val; lt[n+i-1] = i; last[id] = n+i-1; } for(int i = 1; i < n; i++) rt[last[i]] = q; for(int i = 1; i < n+q; i++) g[e[i].c].push_back(i); dsu::init(n); segment_tree::lim = q; for(int i = 2; i <= 1e6; i++) { if(mu[i] == 0) continue; bool flag = false; for(int j = i; j <= 1e6; j += i) { flag |= g[j].size(); for(auto x : g[j]) insert(lt[x], rt[x], x); } if(flag) solve(mu[i]); for(int j = i; j <= 1e6; j += i) for(auto x : g[j]) del(lt[x], rt[x]); } ans[0] = (ll)n*(n-1)/2 + d[0]; for(int i = 1; i <= q; i++) ans[i] = ans[i-1] + d[i]; for(int i = 0; i <= q; i++) cout << ans[i] << "\n"; return0; }
namespace segment_tree { #define ls(i) (i<<1) #define rs(i) (i<<1|1) #define lmid ((l+r)>>1) #define rmid ((l+r+2)>>1) voidsolve(int v, int i, int l, int r) { for(auto j : a[i].t) dsu::merge(e[j].u, e[j].v); ll val = dsuans*v; if(a[i].siz == a[i].t.size()) d[l] += val, d[r+1] -= val; else { solve(v, ls(i), l, lmid); solve(v, rs(i), rmid, r); } for(auto j : a[i].t) dsu::cancel(); } voidpushup(int i) { a[i].siz = a[i].t.size() + a[ls(i)].siz + a[rs(i)].siz; } voidinsert(int ql, int qr, int id, int i, int l, int r) { if(ql <= l and r <= qr) { a[i].t.push_back(id); a[i].siz++; returnvoid(); } if(ql <= lmid) insert(ql, qr, id, ls(i), l, lmid); if(qr >= rmid) insert(ql, qr, id, rs(i), rmid, r); pushup(i); } voiddel(int ql, int qr, int i, int l, int r) { if(ql <= l and r <= qr) { a[i].t.pop_back(); a[i].siz--; returnvoid(); } if(ql <= lmid) del(ql, qr, ls(i), l, lmid); if(qr >= rmid) del(ql, qr, rs(i), rmid, r); pushup(i); } }
namespace dsu { voidinit(int n) { for(int i = 1; i < N; i++) fa[i] = i, siz[i] = 1; } intfind(int x) { return fa[x] == x ? x : find(fa[x]); } ll calc(ll x) { return x*(x-1)/2; } voidmerge(int x, int y) { x = find(x), y = find(y); if(siz[x] < siz[y]) swap(x, y); dsuans -= calc(siz[x]) + calc(siz[y]); siz[x] += siz[y]; dsuans += calc(siz[x]); fa[y] = x; opt.emplace_back(x, y); } voidcancel() { int x = opt.back().first; int y = opt.back().second; opt.pop_back(); dsuans -= calc(siz[x]); siz[x] -= siz[y]; dsuans += calc(siz[x]) + calc(siz[y]); fa[y] = y; } }