*题解:CF702E Analysis of Pathes in Functional Graph
解析
静态查询区间最大值与和可以用 ST 表来解决。而放在基环树上也是一样的道理,设 \(nxt_{i,j}\) 表示从 \(j\) 走 \(2 ^ i\) 条边到达的点,类似地设计出表示最大值与和的状态,倍增即可。
时间复杂度 \(O(n \log k)\)。
代码
/*
*/
#include <bits/stdc++.h>
#define eps 0.0000000001
using namespace std;
typedef long long ll;
typedef unsigned ui;
typedef pair<ll, ll> pii;
const int N = 30 + 5, M = 100000 + 5, P = 450, mod = 1e9 + 7, mod2 = 1e9 + 7, b1 = 131;
int f[M],nxt[N][M],mn[N][M];
ll w[M],sum[N][M];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stderr);
ll n,k;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>f[i];
f[i]++;
nxt[0][i] = f[i];
}
for(int i=1;i<=n;i++){
cin>>w[i];
mn[0][i] = sum[0][i] = w[i];
}
for(int i=1;i<N;i++){
for(int j=1;j<=n;j++){
nxt[i][j] = nxt[i - 1][nxt[i - 1][j]];
mn[i][j] = min(mn[i - 1][j],mn[i - 1][nxt[i - 1][j]]);
sum[i][j] = sum[i - 1][j] + sum[i - 1][nxt[i - 1][j]];
}
}
for(int i=1;i<=n;i++){
ll now = k;
int pos = i;
int resm = 2e9;
ll ress = 0;
for(int i=N - 1;i>=0;i--){
if(now >= (1ll << i)){
resm = min(resm,mn[i][pos]);
ress += sum[i][pos];
pos = nxt[i][pos];
now -= (1ll << i);
}
}
cout<<ress<<" "<<resm<<'\n';
}
return 0;
}

浙公网安备 33010602011771号