#include using namespace std; using pii = pair; using ll = long long; #define NMAX 100010 struct treap { int val, sz, pri; treap *l, *r; treap(int _val = 0) { val = _val; sz = 1; pri = rand(); l = r = nullptr; } }; using Treap = treap*; int fth[NMAX]; vector edges; Treap tr[NMAX]; int size(Treap root) { if(!root) return 0; return root->sz; } void upd(Treap root) { root->sz = 1 + size(root->l) + size(root->r); } void split(Treap root, int val, Treap &l, Treap &r) { if(!root) { l = r = nullptr; return; } if(root->val < val) split(root->r, val, root->r, r), l = root; else split(root->l, val, l, root->l), r = root; } int query(Treap root, int val) { // how many nodes in root are >= val if(!root) return 0; if(root->val < val) return query(root->r, val); else if(root->val == val) return 1 + size(root->r); else return query(root->l, val) + 1 + size(root->r); } void insert(Treap &root, Treap item) { if(!root) { root = item; return; } if(item->pri > root->pri) split(root, item->val, item->l, item->r), root = item; else insert(root->val < item->val ? root->r : root->l, item); upd(root); } int getFth(int a) { if(!fth[a]) return a; return fth[a] = getFth(fth[a]); } bool cmp(const pii &p1, const pii &p2) { return p1.first + p1.second < p2.first + p2.second; } ll queryNewEdges(Treap a, Treap b, int cost) { if(!a) return 0; ll ret = query(b, cost - a->val); ret += queryNewEdges(a->l, b, cost); ret += queryNewEdges(a->r, b, cost); return ret; } void joinTreaps(Treap a, Treap b) { if(!a) return; joinTreaps(a->l, b); joinTreaps(a->r, b); insert(b, a); } ll join(int a, int b) { Treap t1 = tr[getFth(a)], t2 = tr[getFth(b)]; if(size(t1) > size(t2)) swap(a, b), swap(t1, t2); fth[a] = b; //cerr << "join " << a << ' ' << b << '\n'; ll ret = queryNewEdges(t1, t2, a + b); joinTreaps(t1, t2); //cerr << "a.size = " << size(t1) << '\n'; //cerr << "b.size = " << size(t2) << '\n'; return ret; } int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); freopen("data.out", "w", stdout); #endif srand(time(nullptr)); int i, n, x, y; ll nr; cin >> n; for(i = 1; i < n; ++i) { cin >> x >> y; edges.emplace_back(x, y); } sort(edges.begin(), edges.end(), cmp); for(i = 1; i <= n; ++i) tr[i] = new treap(i); for(nr = 0, i = 0; i < edges.size(); ++i) nr += join(edges[i].first, edges[i].second); cout << nr << '\n'; return 0; }