8.16集訓
阿新 • • 發佈:2020-08-16
考試了唄
酒店
觀察題面可以得到:樹上三個點之間的距離兩兩相同,說明距離一定是偶數,並且終點一定重合
考慮列舉中點,要求的就是三個點到中點距離相同的方案數
#include <bits/stdc++.h> #define LL long long #define debug using namespace std; const int N = 1e5+66; int head[N], to[N], nex[N], cnt; inline void add(int x, int y) { to[++ cnt] = y; nex[cnt] = head[x]; head[x] = cnt; } inline long long read() { long long s = 0, f = 1; char ch; while(!isdigit(ch = getchar())) (ch == '-') && (f = -f); for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48)); return s * f; } int md, g[N], d[N]; LL f1[N], f2[N], f3[N]; inline void dfs(int x, int fa) { int i, y; md = max(md, d[x]), ++ g[d[x]]; for (i = head[x]; i; i = nex[i]) { y = to[i]; if (y == fa) continue; d[y] = d[x] + 1; dfs(y, x); } } inline LL query(int x, int n) { int i, j, y; LL ans(0); // memset(f1, 0, sizeof f1),memset(f2, 0, sizeof f2), memset(f3, 0, sizeof f3); for (i = head[x]; i; i = nex[i]) { y = to[i]; d[y] = md = 1, dfs(y, x); for (j = md; j >= 1; -- j) { f3[j] += (LL)f2[j]*g[j]; f2[j] += (LL)f1[j]*g[j]; f1[j] += (LL)g[j]; g[j] = 0; } } for (i = 1; i <= n; ++ i) ans += f3[i]; for ( i = 1; i <= md<<1; ++ i) f1[i] = f2[i] = f3[i] = 0; for (i = 1; i <= n; ++ i) return ans; } inline int thestars() { int i, n, x, y; LL res(0); n = read(); for (i = 1; i < n; ++ i) { x = read(); y = read(); add(x, y); add(y, x); } for (i = 1; i <= n; ++ i) res += query(i, n); cout << res; return 0; } int youngore = thestars(); signed main() {;}
最長道路tree
樹的直徑加並查集
把權值從大到小排序,按照順序加點,維護每個聯通塊的最長鏈乘以當前點權值作為貢獻
考慮在連上一條邊之後,如何快速找到新的直徑?
這裡GXZ大佬給出了我們一個結論:將兩棵樹連成一棵,新樹的直徑的兩端點只可能是原來兩棵樹裡面兩條直徑四個端點中的某一個
要用並查集維護樹的直徑長度以及端點位置,倍增求LCA
開LL
PS:如果用LL全部替換掉int的話,大概率會T,我們只需要對查詢函式以及答案開LL就可以了
還有,初始化的時候,儘量多初始化一點,但是也不要用memset,大概率會T
#include <bits/stdc++.h> #define LL long long #define debug using namespace std; //東方之珠 整夜未眠! const int N = 1e5+66; int head[N], to[N], nex[N], cnt; inline void add(int x, int y) { to[++ cnt] = y; nex[cnt] = head[x]; head[x] = cnt; } int v[N], d[N], f[N], id[N]; int fa[N][18], logs[N], px[N], py[N]; LL ans(0); inline bool cmp(int a, int b) {return v[a] > v[b];} inline int find(int x) {return f[x] == x ? x : f[x] = find(f[x]);} inline void dfs(int x) { int i, y; for (i = 1; (1 << i) <= d[x]; ++ i) fa[x][i] = fa[fa[x][i - 1]][i - 1]; for (i = head[x]; i; i = nex[i]) { y = to[i]; if (y == fa[x][0]) continue; fa[y][0] = x; d[y] = d[x] + 1; dfs(y); } } inline int lca(int x, int y) { int i; if (d[x] < d[y]) swap(x, y); for (i = logs[d[x] - d[y]]; ~i; -- i) if (d[x] - d[y] >= (1 << i)) x = fa[x][i]; if (x == y) return x; for (i = logs[d[x]]; ~i; -- i) if (d[x] >= (1 << i) && fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; return fa[x][0]; } inline int dis(int x, int y) {return d[x] + d[y] - (d[lca(x, y)] << 1);} inline void solve(int x) { int i, tx, ty, t, vm, vx, vy, y; for (i = head[x]; i; i = nex[i]) { y = to[i]; if (f[y]) { tx = find(x), ty = find(y), vm = -1; if (vm < (t = dis(px[tx], py[tx]))) vm = t, vx = px[tx], vy = py[tx]; if (vm < (t = dis(px[ty], py[ty]))) vm = t, vx = px[ty], vy = py[ty]; if (vm < (t = dis(px[tx], px[ty]))) vm = t, vx = px[tx], vy = px[ty]; if (vm < (t = dis(px[tx], py[ty]))) vm = t, vx = px[tx], vy = py[ty]; if (vm < (t = dis(py[tx], px[ty]))) vm = t, vx = py[tx], vy = px[ty]; if (vm < (t = dis(py[tx], py[ty]))) vm = t, vx = py[tx], vy = py[ty]; f[ty] = tx, px[tx] = vx, py[tx] = vy; } } tx = find(x); ans = max(ans, (LL)v[x] * (dis(px[tx], py[tx]) + 1)); } inline int thestars() { int i, x, y, n; cin >> n; for (i = 1; i <= n; ++ i) scanf ("%d", &v[i]), id[i] = i; for (i = 2; i <= n; ++ i) { scanf ("%d%d", &x, &y); add(x, y); add(y, x); logs[i] = logs[i >> 1] + 1; } dfs(1); sort(id + 1, id + n + 1, cmp); for (i = 1; i <= n; ++ i) { f[id[i]] = px[id[i]] = py[id[i]] = id[i]; solve(id[i]); } cout << ans; return 0; } int youngore = thestars(); signed main() {;}
精神汙染
不會!