#pragma comment(linker, "/STACK:16777216") #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define REP(i,n) for(int i = 0, _n = (n); i < _n; i++) #define REPD(i,n) for(int i = (n) - 1; i >= 0; i--) #define FOR(i,a,b) for (int i = (a), _b = (b); i <= _b; i++) #define FORD(i,a,b) for (int i = (a), _b = (b); i >= _b; i--) #define DOWN(i,a,b) for (int i = (a), _b = (b); i >= _b; i--) #define FOREACH(it,c) for (__typeof((c).begin()) it=(c).begin();it!=(c).end();it++) #define RESET(c,x) memset (c, x, sizeof (c)) #define sqr(x) ((x) * (x)) #define PB push_back #define MP make_pair #define F first #define S second #define ALL(c) (c).begin(), (c).end() #define SIZE(c) (c).size() #define DEBUG(x) { cerr << #x << " = " << x << endl; } #define PR(a,n) {cerr<<#a<<" = "; FOR(_,1,n) cerr << a[_] << ' '; cerr < num[v]) swap(u, v); cost[v] ++; cost[u] --; } callCost(1); //cerr <<"callCost" << endl; FOR (i, 1, n) cout << i << ": " << cost[i] << endl; } map f; int cnt[322222]; void editCost() { FOR (i, 2, n) cnt[cost[i]]++; int small = 0, big = 0; FOR (i, 1, m) if (cnt[i] > sqm) f[i] = ++big; small = sqm; FOR (i, 1, m) if (cnt[i] > 0 && cnt[i] <= sqm) f[i] = ++small; FOR (i, 1, n) if (cost[i]) cost[i] = f[cost[i]]; } int prev[maxn]; set > node[4 * maxn]; void update(int s, int l, int r, int u, int v) { if (u < l || r < u) return; node[s].insert(MP(-num[v], v)); if (l == r) return; update(s * 2, l, (l + r) / 2, u, v); update(s * 2 + 1, (l + r) / 2 + 1, r, u, v); } int get(int s, int l, int r, int u, int v, int i) { if (r < u || v < l) return -1; if (u <= l && r <= v) { set >:: iterator it; it = node[s].upper_bound(MP(-num[i], n + 1)); /*if (i == 2) { cerr <<"??????" << endl; FOREACH(it, node[s]) cerr << (*it).first << " " << (*it).second << endl; } */ if (it == node[s].end()) return -1; return (*it).second; } int x = get(s * 2, l, (l + r) / 2, u, v, i); int y = get(s * 2 + 1, (l + r) / 2 + 1, r, u, v, i); if (x == -1 || y == -1) return max(x, y); if (num[x] > num[y]) return x; else return y; } void callPrev() { FOREACH(it, add) { int u = (*it).first; int v = (*it).second; if (num[u] < num[v]) swap(u, v); update(1, 1, n, num[u], v); //cerr <<"??" << u << " " << num[u] << " " << num[v] << " " << v << endl; } FOR (i, 1, n) prev[i] = get(1, 1, n, Low[i], High[i], i); //cerr <<"callPrev" << endl; FOR (i, 1, n) cout << i << ": " << prev[i] << endl; } vector LIST[322222]; long long res = 0; int sum[maxn][sqm]; int ancestor(int u, int v) { return (num[u] <= num[v] && done[u] >= done[v]); } void dfsCall(int u) { if (u == 1) memset(sum[u], 0, sizeof (sum[u])); if (prev[u] != -1 && cost[u] > 0) { if (cost[u] <= sqm) res += sum[u][cost[u]] - sum[prev[u]][cost[u]] - 1; else FOREACH(it, LIST[cost[u]]) if (prev[u] != *it && *it != u && ancestor(prev[u], *it) && ancestor(*it, u)) res++; } FOREACH(it, adj[u]) if (pa[*it] == u) { FOR (i, 1, sqm) sum[*it][i] += sum[u][i] + (cost[*it] == i); dfsCall(*it); } } long long findRes() { FOR (i, 2, n) if (cost[i] > sqm) LIST[cost[i]].PB(i); dfsCall(1); res += cnt[1]; res += (long long) cnt[0] * (m - cnt[0]) + (long long) cnt[0] * (cnt[0] - 1) / 2; return res; } int main() { //freopen("15.in", "r", stdin); freopen("15.out", "w", stdout); enter(); findCost(); editCost(); callPrev(); cout << findRes() << endl; return 0; }