蒟蒻为了写这一题,再会倍增的情况下去学了树剖,结果50分,其他的全 TLE 。换用倍增,100分,最后一个点 WA 。不是说树剖会比倍增快吗?
接下来是倍增代码,求调:
#include<bits/stdc++.h>
using namespace std;
int n,q,m,a,b,head[100001],cnt=0,l[100001],f[100001][20],d[100001];
struct note{
int t,ne;
}e[200001];
void add(int x,int y)
{
cnt++,e[cnt].t=y,e[cnt].ne=head[x],head[x]=cnt;
}
void ycl(int now,int fa)
{
f[now][0]=fa,d[now]=d[fa]+1;
for(int i=1;i<=l[d[now]];i++)
f[now][i]=f[f[now][i-1]][i-1];
for(int i=head[now];i>0;i=e[i].ne)
if(e[i].t!=fa)
ycl(e[i].t,now);
}
int lca(int x,int y)
{
if(d[x]<d[y])
swap(x,y);
while(d[x]>d[y])
x=f[x][l[d[x]-d[y]]];
if(x==y)
return x;
for(int i=l[d[x]];i>=0;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
int main()
{
cin>>n;
for(int i=1;i<n;i++)
cin>>a,add(a,i),add(i,a);
for(int i=2;i<=n;i++)
l[i]=l[i>>1]+1;
ycl(0,0);
cin>>q;
while(q--)
{
cin>>m>>a;
for(int i=1;i<m;i++)
cin>>b,a=lca(a,b);
cout<<a<<"\n";
}
return 0;
}
然后是树剖代码,麻烦 dalao 根据这份代码解决一下蒟蒻的疑问:
#include<bits/stdc++.h>
using namespace std;
int n,q,m,a,b,head[100001],cnt=0,f[100001],d[100001],si[100001],hs[100001],db[100001];
struct note{
int t,ne;
}e[200001];
void add(int x,int y)
{
cnt++,e[cnt].t=y,e[cnt].ne=head[x],head[x]=cnt;
}
void ycl(int now)
{
hs[now]=-1,si[now]=1,d[now]=d[f[now]]+1;
for(int i=head[now];i>0;i=e[i].ne)
if(e[i].t!=f[now])
{
f[e[i].t]=now;
ycl(e[i].t);
si[now]=si[now]+si[e[i].t];
if(hs[now]==-1||si[e[i].t]>hs[now])
hs[now]=e[i].t;
}
}
void l(int now,int t)
{
db[now]=t;
if(hs[now]==-1)
return;
l(hs[now],t);
for(int i=head[now];i>0;i=e[i].ne)
if(e[i].t!=hs[now]&&e[i].t!=f[now])
l(e[i].t,e[i].t);
}
int lca(int x,int y)
{
while(db[x]!=db[y])
if(d[db[x]]<d[db[y]])
y=f[db[y]];
else
x=f[db[x]];
if(d[x]<d[y])
return x;
else
return y;
}
int main()
{
cin>>n;
for(int i=1;i<n;i++)
cin>>a,add(a,i),add(i,a);
ycl(0);
l(0,0);
cin>>q;
while(q--)
{
cin>>m>>a;
for(int i=1;i<m;i++)
cin>>b,a=lca(a,b);
cout<<a<<"\n";
}
return 0;
}