leetcode2836 在传球游戏中最大化函数值
n名玩家在玩传球游戏,编号为i的玩家固定会把球传给编号为r[i]的玩家,任选一名玩家开始传球,恰好传k次,得分为这k次传球内所有接触过球的玩家的编号之和,如果玩家多次触球,则累加多次。问从哪个玩家开始传,能获得最大总得分,求最大得分。
1<=n<=1E5; 0<=r[i]<n; 1<=k<=1E10
分析:与倍增法求lca类似,记f[i][j]表示从玩家i开始传2^j次后到达的玩家编号,w[i][j]表示对应的得分(不含最后接球玩家)。
using i64 = long long;
class Solution {
public:
long long getMaxFunctionValue(vector<int>& r, long long k) {
int n = r.size();
std::vector<std::vector<int>> f(n, std::vector<int>(35, 0));
std::vector<std::vector<i64>> w(n, std::vector<i64>(35, 0));
for (int i = 0; i < n; i++) {
f[i][0] = r[i];
w[i][0] = i;
}
for (int j = 1; j < 35; j++) {
for (int i = 0; i < n; i++) {
f[i][j] = f[f[i][j - 1]][j - 1];
w[i][j] = w[i][j - 1] + w[f[i][j - 1]][j - 1];
}
}
i64 ans = 0;
for (int i = 0; i < n; i++) {
i64 cur = 0;
int x = i;
for (int t = 34; t >= 0; t--) {
if ((1LL << t) & k) {
cur += w[x][t];
x = f[x][t];
}
}
ans = std::max(ans, cur + x);
}
return ans;
}
};