[模拟赛]最亲祖先
[模拟赛] 最亲祖先

思路:
考虑为链的情况,显然使用单调栈。在此基础上,树的做法便显而易见了。用链表实现栈,弹出元素时使用倍增。时间复杂度\(O(nlog_2n)\)
\[\mathfrak{Talk\ is\ cheap,show\ you\ the\ code.}
\]
#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define Type template<typename T>
# define read read1<ll>()
Type T read1(){
T t=0;
char k;
bool vis=0;
do (k=getchar())=='-'&&(vis=1);while('0'>k||k>'9');
while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
return vis?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
ll a[500005];
int s,h[500005],sta[500005],la[500005][21];
vector<int>G[500005];
double ans[500005];
void dfs(int n,int w){
la[s+1][0]=w;w=s+1;
for(int i=0;i<20;++i)la[w][i+1]=la[la[w][i]][i];
for(int x=20;~x;--x)
if(la[la[w][x]][0]&&(a[la[w][x]]-a[n])*(h[la[w][x]]-h[la[la[w][x]][0]])>(a[la[la[w][x]][0]]-a[la[w][x]])*(h[n]-h[la[w][x]]))w=la[w][x];
w=la[w][0];
if(n!=1)ans[n]=1.0*(a[w]-a[n])/(h[n]-h[w]);
la[n][0]=w;
for(int i=0;i<20;++i)la[n][i+1]=la[la[n][i]][i];
for(int i=0;i<G[n].size();++i)
h[G[n][i]]=h[n]+1,dfs(G[n][i],n);
}
int main(){
//fre("dearest");
s=read;
for(int i=1;i<=s;++i)a[i]=read;
for(int i=2;i<=s;++i){
int x=read;
G[x].push_back(i);
}
dfs(1,0);
for(int i=2;i<=s;++i)
printf("%.9f\n",ans[i]);
return 0;
}
因果乃旋转纺车,光彩之多面明镜
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存

浙公网安备 33010602011771号