题解:P7543 [CEOI2011] Treasure Hunt
P7543
唐题,抢个首发题解。
如果每次只加入一个点,那么处理新点的倍增数组,使用倍增即可解决问题。
考虑将每条链缩成一个点,然后处理每条链的倍增数组。查询两个点的 LCA 可以先从链上做 LCA,找到两点 LCA 的所在链,然后从两个点所在链往上倍增跳,即可求出 LCA 的具体位置。同样的,跳链的倍增也可以求出 k 级祖先。于是这个题就做完了。复杂度
代码:
#include<bits/stdc++.h>
using namespace std;
int q,n,k1,k2,k3,k4,k5,k6,k7,k8,k9,idx;
string s;
struct chn{
int st;
int ed;
int dep;
int chdep;
int fa[23];
}P[400003];
set<pair<int,int> >R;
int getchn(int X){
auto p=R.lower_bound(make_pair(X+1,-1000000));
if(p==R.begin())return -1;
p--;
return (*p).second;
}
int getdep(int X){
int uu=getchn(X);
return P[uu].dep+(X-P[uu].st);
}
int chnLCA(int X,int Y){
int c=20;
if(P[X].chdep<P[Y].chdep)swap(X,Y);
while(c--)if(P[P[X].fa[c]].chdep>=P[Y].chdep)X=P[X].fa[c];
c=20;
while(c--)if(P[X].fa[c]!=P[Y].fa[c])X=P[X].fa[c],Y=P[Y].fa[c];
if(X==Y)return X;
return P[X].fa[0];
}
int jumpDEP(int X,int chn,int tgt){
if(chn==tgt)return P[chn].dep+(X-P[chn].st);
for(int i=20;i>=0;i--)if(P[P[chn].fa[i]].dep>P[tgt].dep)chn=P[chn].fa[i];
return P[chn].dep-1;
}
int KthPar(int X,int chn,int k){
if(X-P[chn].st<k){k-=(X-P[chn].st);X=P[chn].st;}
else return X-k;
for(int i=20;i>=0;i--){
if(!P[chn].fa[i])continue;
if(P[chn].dep-P[P[chn].fa[i]].dep<=k){
k-=P[chn].dep-P[P[chn].fa[i]].dep;
chn=P[chn].fa[i];
}
}
if(k==0)return P[chn].st;
return P[P[chn].fa[0]].st+((P[chn].dep-k)-P[P[chn].fa[0]].dep);
}
int main(){
freopen("P7543.in","r",stdin);
ios::sync_with_stdio(false);
cin>>q;
idx=n=1;
P[n=1].st=P[n=1].ed=P[1].dep=P[1].chdep=1;
R.insert(make_pair(1,1));
while(q--){
cin>>s;
if(s[0]=='P'){
cin>>k1>>k2;
P[++n].st=idx+1;
P[n].ed=idx+k2;
idx+=k2;
P[n].fa[0]=getchn(k1);
P[n].dep=P[P[n].fa[0]].dep+(k1-P[P[n].fa[0]].st)+1;
P[n].chdep=P[P[n].fa[0]].chdep+1;
R.insert(make_pair(P[n].st,n));
for(int i=1;i<=20;i++)P[n].fa[i]=P[P[n].fa[i-1]].fa[i-1];
}
else{
cin>>k1>>k2;
k3=getchn(k1);
k4=getchn(k2);
k5=chnLCA(k3,k4);
k6=getdep(k1)+getdep(k2)-2*min(jumpDEP(k1,k3,k5),jumpDEP(k2,k4,k5));
if(getdep(k1)>getdep(k2))cout<<KthPar(k1,k3,(k6/2))<<'\n';
else cout<<KthPar(k2,k4,k6-(k6/2))<<'\n';
}
}
return 0;
}