CF1055F Tree and XOR

Link
做个每个点到根的异或和,那么现在问题又变成了求第\(k\)小的\(a_i\operatorname{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);
}
posted @ 2020-04-26 22:01  Shiina_Mashiro  阅读(185)  评论(0编辑  收藏  举报