求助TLE
  • 板块P5557 旅行
  • 楼主SDNetFriend
  • 当前回复1
  • 已保存回复1
  • 发布时间2020/10/1 05:52
  • 上次更新2023/11/5 12:21:03
查看原帖
求助TLE
206258
SDNetFriend楼主2020/10/1 05:52

算起来复杂度大概是mlogn左右,但真的一直TLE,真的想不通怎么T掉的,只A了前两个点

蒟蒻求助

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <cmath>
using namespace std;
const long long MAXN=4e5+5,MAXM=3e5+5;
long long n,a[MAXN][35],m,S,t1,t2,lgn;
bool Vis[MAXN]={0};
long long To[MAXN],Start[MAXN],Len,Tmp,In[MAXN]={0},Ring[MAXN],Index[MAXN],From[MAXN]={0};//a[i][0]µ¥¶À¿¼ÂÇ RingΪ0_Len-1µÄϱ귶Χ 
void getTo(long long Now){//Right ÓÃÀ´Ñ°ÕÒ±¶Ôö£¬²»ÔÚ»·ÉϵĵãλÖõÄËÑË÷ O(n)
	long long Begin=Now;
	while(Vis[Now]==false){ 
		//cout<<"Now::"<<Now<<endl;
		From[a[Now][0]]=Now;
		Vis[Now]=true;
		Now=a[Now][0];
	}
	while(true){
		for(register long long i=1;a[a[Now][i-1]][i-1]!=0&&i<=lgn;++i){
			//cout<<"Now::"<<Now<<endl;
			a[Now][i]=a[a[Now][i-1]][i-1];
		}
		To[Now]=To[a[Now][0]]+1;
		Start[Now]=Start[a[Now][0]];
		if(Now==Begin||From[Now]==0)break;
		Now=From[Now];
	}
}
void getRing(){//Right Ñ°ÕÒ»·µÄ³¤¶È£¬²¢±ê¼Ç O(n)
	bitset<MAXN> been;
	long long Now=1,Origin;
	while(true){
		if(been[Now]==1)break;
		been[Now]=1;
		Now=a[Now][0];
	}
	Origin=Now;long long tmp=0;
	Len=0;
	while(true){
		if(Now==Origin)++tmp;if(tmp==2)break;
		Ring[Len]=Now;Index[Now]=Len;Vis[Now]=true;
		//cout<<"la::"<<Index[Now]<<" "<<Now<<endl;
		++Len;
		To[Now]=0;Start[Now]=Now;
		Now=a[Now][0];
	}
	for(register long long i=1;i<=n;++i)
		if(In[i]==0)
			getTo(i);
}
long long ModPow(long long t1,long long t2,long long Mod){//Right Çót1^t2%Mod O(log2 t2)
	if(t2==0)return 1;
	long long tmp=t1%Mod,Ans=1;
	while(t2!=0){
		if(t2&1)Ans=(tmp*Ans)%Mod;
		tmp=(tmp*tmp)%Mod;
		t2>>=1;
	}
	return Ans%Mod;
}
long long Find(long long Now,long long Go){//Right Ñ°ÕÒNowÏòÇ°Go¸öλÖõÄϱê O(log2 Go)
	long long Sum=0;
	while(Go!=0){
		if(Go&1)Now=a[Now][Sum];
		++Sum;
		Go>>=1;
	} 
	return Now;
}
int main(){
	scanf("%lld",&n);
	lgn=log(n)/log(2)+1e-7;
	for(register long long i=1;i<=n;++i)
		scanf("%lld",&a[i][0]),++In[a[i][0]];
	for(register long long i=0;i<=n;++i)
		To[i]=-1,Start[i]=0;
	getRing();
//	cout<<"To&Start::"<<endl;
//	for(register long long i=1;i<=n;++i)	
//		cout<<To[i]<<" "<<Start[i]<<endl;
//	cout<<"Len::"<<Len<<endl;
//	cout<<"a[i][j]::"<<endl;
//	for(register long long i=1;i<=n;++i){
//		for(register long long j=0;j<=32;++j){
//			if(a[i][j]==0){
//				cout<<0<<endl;
//				break;
//			}
//			cout<<a[i][j]<<" ";
//		}
//	}
//	cout<<"Ring::"<<endl;
//	for(register long long i=0;i<Len;++i)
//		cout<<Ring[i]<<" ";
//	cout<<endl;
	scanf("%lld",&m); 
	long long Ans,tmp1;
	for(register long long i=1;i<=m;++i){
		scanf("%lld%lld%lld",&S,&t1,&t2);
		//O(m*log2 t2)
		if(To[S]==0){
			Tmp=ModPow(t1,t2,Len);
			if(Index[Start[S]]+Tmp>=Len)Tmp-=Len;
			if(Index[Start[S]]+Tmp<0)Tmp+=Len;
			Ans=Ring[Index[Start[S]]+Tmp];
		}
		else if(t2<=log((double)To[S])/log((double)t1)){
			Ans=Find(S,ModPow(t1,t2,MAXN));
		}else{
			Tmp=ModPow(t1,t2,Len);
			tmp1=To[S]%Len;
			if(Index[Start[S]]+Tmp-tmp1>=Len)Tmp-=Len;
			if(Index[Start[S]]+Tmp-tmp1<0)Tmp+=Len;
			//cout<<" "<<Index[S]+Tmp-tmp1<<endl;
			Ans=Ring[Index[Start[S]]+Tmp-tmp1];
		}
		printf("%lld\n",Ans);
	}
	return 0;
}
/*
10
2 3 1 1 4 5 6 7 8 9
7
8 3 1
10 5 1
10 2 2
4 2 4
4 3 1
4 2 1
4 1 1


5 5 6 1 3 2 1
*/
/*
11
2 3 4 1 1 5 6 2 8 8 10
5
11 4 2
7 2 1
9 3 2
9 128 1000000000
2 3 2

3 5 1 ~ 3
*/
2020/10/1 05:52
加载中...