题目略
乍一看还以为是道LCA题,再一看数据范围,哦,数学题。。。
本来这题后三个点我是过不了的
开O2后AC
这题。。。。看眼数据范围就知道是数学题了(掩面
手动列一下各点的爹:
1 2 3 4 5 6 7 8 9 10 11 12 13
1 1 1 1 2 1 2 3 1 2 3 4 5
你会发现,就是个斐波那契。。。。。。
然后,因为fib是指数级增长的,所以打一下fib小于1e12的前缀和的表:
ll biao[59]={0,3,4,6,9,14,22,35,56,90,145,234,378,611,988,1598,2585,4182,6766,10947,17712,28658,46369,75026,121394,196419,317812,514230,832041,1346270,2178310,3524579,5702888,9227466,14930353,24157818,39088170,63245987,102334156,165580142,267914297,433494438,701408734,1134903171,1836311904,2971215074,4807526977,7778742050,12586269026,20365011075,32951280100,53316291174,86267571273,139583862446,225851433718,365435296163,591286729880,956722026042,1548008755921};
然后查找的时候只要二分:biao[mid]<=a<biao[mid+1]就可以了,复杂度一个log
后面的话用set维护链,爬链查找就可以了
注意要及时退出,并且清空set
附代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<set> 4 #define ll long long 5 using namespace std; 6 template<typename T> 7 inline void read(T &x){ 8 char ch;while((ch=getchar()),(ch>'9'||ch<'0')); 9 x=ch-'0';while((ch=getchar()),(ch>='0'&&ch<='9')) x=x*10+ch-'0'; 10 } 11 int m; 12 ll biao[59]={0,3,4,6,9,14,22,35,56,90,145,234,378,611,988,1598,2585,4182,6766,10947,17712,28658,46369,75026,121394,196419,317812,514230,832041,1346270,2178310,3524579,5702888,9227466,14930353,24157818,39088170,63245987,102334156,165580142,267914297,433494438,701408734,1134903171,1836311904,2971215074,4807526977,7778742050,12586269026,20365011075,32951280100,53316291174,86267571273,139583862446,225851433718,365435296163,591286729880,956722026042,1548008755921}; 13 inline ll find(ll a){ 14 if(a==1||a==2||a==3||a==4) return 1; 15 int l=0,r=58,mid; 16 while(l-r){ 17 mid=l+((r-l)>>1); 18 if(a>=biao[mid]&&a<biao[mid+1]){return a-biao[mid]+1;} 19 if(a>biao[mid]) l=mid; 20 if(a<biao[mid]) r=mid; 21 } 22 } 23 set<ll> t; 24 int main(){ 25 //freopen("in","r",stdin); 26 //freopen("out","w",stdout); 27 read(m); 28 register int i; 29 register ll a,b; 30 for(i=1;i<=m;++i){ 31 read(a),read(b); 32 t.insert(a); 33 while(true){a=find(a),t.insert(a);if(a==1)break;} 34 if(t.count(b)){printf("%lld ",b),t.clear();continue;} 35 while(true){ 36 b=find(b); 37 if(t.count(b)){printf("%lld ",b);break;} 38 } 39 t.clear(); 40 } 41 return 0; 42 }