环上倍增,直接倍增

/*
只需要直到下一个走到点是谁,那就可以进行倍增的处理
而不需要去是否成环的问题
直到他的下一个点就可以了 


环上倍增也是一个道理,可以直接走下去 
*/
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define br cout<<"----------------------------\n";
const int M=1e5+5;

int n,k;

//向下走是谁,最小值,权值和 
int f1[M][36],f2[M][36],f3[M][36];

void init_st() {
	for(int j=1;j<=35;j++)
		for(int i=1;i<=n;i++) { //这里需要延长一点 
			f1[i][j]=f1[f1[i][j-1]][j-1];
			f2[i][j]=min(f2[i][j-1],f2[f1[i][j-1]][j-1]);
			f3[i][j]=f3[i][j-1]+f3[f1[i][j-1]][j-1];
//			cout<<f1[i][j]<<' '<<f2[i][j]<<' '<<f3[i][j]<<'\n';
		}
}

int query1(int st,int k) {
	int ans=0;
	for(int i=35;i>=0;i--)
		if((1ll<<i)<=k)k-=(1ll<<i),ans+=f3[st][i],st=f1[st][i];
	return ans;
}

int query2(int st,int k) {
	int mn=1e9;
	
	for(int i=35;i>=0;i--)
		if((1ll<<i)<=k)k-=(1ll<<i),mn=min(mn,f2[st][i]),st=f1[st][i];
	return mn;
}



void solve() {
	cin>>n>>k;
	for(int i=1;i<=n;i++)cin>>f1[i][0],f1[i][0]++;
	for(int i=1,x;i<=n;i++)cin>>x,f2[i][0]=f3[i][0]=x;
	init_st();
	for(int i=1;i<=n;i++)
		cout<<query1(i,k)<<' '<<query2(i,k)<<'\n';
}

signed main() {
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	solve();
	return 0;
}
posted @ 2023-07-05 13:26  basicecho  阅读(38)  评论(0)    收藏  举报