Link
做个每个点到根的异或和,那么现在问题又变成了求第(k)小的(a_ioperatorname{xor}a_j)。
Trie树+高位贪心即可。这个Trie树我们可以从上往下一层层建,每一层建的时候可以把上一层的Trie清空,这样可以做到(O(n))空间。
#include<cctype>
#include<cstdio>
#include<cstring>
using i64=long long;
const int N=1000007;
int tot,p[N],q[N];i64 a[N];
struct node{int size,ch[2];}t[N];
char ibuf[1<<25|1],*iS=ibuf;
i64 read(){i64 x=0;while(isspace(*iS))++iS;while(isdigit(*iS))(x*=10)+=*iS++&15;return x;}
int get(int p,int d){return t[p].ch[d]? t[p].ch[d]:t[p].ch[d]=++tot;}
int main()
{
fread(ibuf,1,1<<25,stdin);
int n=read();i64 k=read(),ans=0;
for(int i=2,fa;i<=n;++i) fa=read(),a[i]=a[fa]^read();
for(int d=61;~d;--d)
{
memset(t,0,12*tot+12);i64 s=tot=0;
for(int i=1;i<=n;++i) ++t[p[i]=get(p[i],a[i]>>d&1)].size;
for(int i=1;i<=n;++i) s+=t[t[q[i]].ch[a[i]>>d&1]].size;
for(int i=1;i<=n;++i) q[i]=t[q[i]].ch[(a[i]>>d&1)^(k>s)];
if(k>s) k-=s,ans|=1ll<<d;
}
printf("%lld",ans);
}