题目链接:在传球游戏中最大化函数值
题解:倍增
1. 和倍增寻找最近公共祖先的方法一样,其实也是一种动态规划
2. f[i][j]:第i个节点传球2^j次最后到达的节点
g[i][j]:第i个节点传球2^j次,球经过的结点的编号和,不算首结点
3. f[i][j] = f[f[i][j-1]][j-1]
g[i][j] = g[i][j-1] + g[f[i][j-1]][j-1]
4. 结点i传球k次,球经过结点的编号和:每次把球传递2的幂次,最多传ceil(log2(k))
PS:如果k比较小,可以预处理log2[1...k]加速,如果k比较大,枚举二进制位即可
代码示例:
class Solution {
public:
#define N 100005
#define M 36
#define ll long long
long long getMaxFunctionValue(vector<int>& receiver, long long k) {
int n = receiver.size();
vector<vector<int>> f(n, vector<int>(M));
vector<vector<ll>> g(n, vector<ll>(M));
for (int i = 0; i < n; ++i) f[i][0] = g[i][0] = receiver[i];
for (int j = 1; j < M; ++j) {
for (int i = 0; i < n; ++i) {
f[i][j] = f[f[i][j - 1]][j - 1];
g[i][j] = g[i][j - 1] + g[f[i][j - 1]][j - 1];
}
}
ll ans = 0;
for (int i = 0, u; i < n; ++i) {
ll sum = u = i;
for (int j = 0; j < M; ++j) if ((k >> j) & 1) {
sum += g[u][j];
u = f[u][j];
}
ans = max(ans, sum);
}
return ans;
}
};