链接:
对于这种边权难以直接维护的都直接考虑brouvka算法。 显然,我们要做的是实现一个可以查询&x最大的数据结构。 可以先对于所有权值建立一颗01-trie树。 考虑在trie树查询答案的过程,可以考虑一个从高位到低位的贪心。 当x的第i位为1时,最优策略一定是能走1就走1。 当x的第i位为0时,既可以走0也可以走1。 因此可以用一个类似线段树合并的方式,把每一个trie树上的节点右儿子合并到左儿子上。 然后直接按照brouvka算法的套路搞一下就行了。#include#include #include #include #include #include #include #include #include #include #define N 220000#define L 200000#define M 8000000#define eps 1e-7#define inf 1e9+70#define db double#define ll long long#define ldb long doubleusing namespace std;inline int read(){ char ch=0; int x=0,flag=1; while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*flag;}int v[N],f[N];int find(int x){if(x!=f[x])f[x]=find(f[x]);return f[x];}void merge(int x,int y){f[find(x)]=find(y);}struct node{int x,y;}w[N],p[N];bool operator<(node a,node b){ if(a.y!=b.y)return a.y maxv[y])mixv[x]=max(mixv[x],maxv[y]); maxv[x]=max(maxv[x],maxv[y]); } void pushup(int o) { maxv[o]=mixv[o]=-inf; upd(o,lson);upd(o,rson); } void insert(int &o,int t,int x,int id) { if(!o)o=newnode(); if(!t) { if(maxv[o]>id)mixv[o]=max(mixv[o],id); if(maxv[o]