codeforces 888Gソリューション

トピックポータル

主なアイデア:nnがありますn個のポイントがあり、各ポイントには重みがあります。2つのポイント間のエッジの長さは、2つのポイントの重みのXOR値です。最小全域木のエッジの重みの合計を見つけます。

回答

Boruvka \ text {Boruvka}Boruvkaアルゴリズムが使用されます。2つの接続されたブロックの最短辺を計算するとき、01トライの2つのブロック01〜\ text {trie}がそれぞれ維持されます0 1 トライ 、最短の辺は、そのうちの1つをトラバースすることで計算できます。具体的には、貪欲です。最上位ビットから開始して、各ビットは可能な限り同じです。次に、2つの部分をマージするときに、それらのトライ\ text {trie}を追加しますトライもマージされ、最後にすべての数字を含むトライが取得されます\ text {trie}トライ

この方法の問題は、各ペアの最短辺の長さを毎回見つける方法がないことです。さらに、接続されたブロックの最短辺を見つけることは不可能ですが、これは良いアイデアを提供します。接続されたブロックをマージする順序を決定する必要がある場合、答えを見つけるのは簡単です。

すべての数字を含むトライ\ text {trie}を検討してくださいトライ、彼のノードの1つのサブツリーはポイントのセットに対応します。各ポイントの左と右のサブツリーを下から上にマージするには、この戦略が最適なマージ順序であることがわかります。接続されたブロックがマージされるとき、それらは最短エッジに沿って他のものとマージされなければなりません。

したがって、左サブツリーと右サブツリーのマージの最短側のみを要求する必要があるたびに、左サブツリーの各ポイントを右サブツリーに勢いよく投げて、貪欲に実行できます。時間の複雑さはO(n log⁡2 n)O( n \ log ^ 2n)O nlo g2n

コードは以下のように表示されます:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 200010
#define inf 999999999
#define ll long long

int n,a[maxn];
struct node{
    
    
	int l,r,dep;
	node *ch[2];
	node(int Dep):l(inf),r(0),dep(Dep){
    
    ch[0]=ch[1]=NULL;}
}*root;
void insert(int x){
    
    
	node *now=root;
	for(int i=29;i>=0;i--){
    
    
		int c=a[x]>>i&1;
		if(!now->ch[c])now->ch[c]=new node(i-1);
		now=now->ch[c];
		now->l=min(now->l,x);
		now->r=max(now->r,x);
	}
}
int ask(node *now,int x){
    
    
	if(now->dep<0)return 0;
	int c=x>>(now->dep)&1;
	if(now->ch[c])return ask(now->ch[c],x);
	else return ask(now->ch[c^1],x)+(1<<(now->dep));
}
ll solve(node *now){
    
    
	if(now->ch[0]&&now->ch[1]){
    
    
		int mi=inf;
		for(int i=now->ch[0]->l;i<=now->ch[0]->r;i++)mi=min(mi,ask(now->ch[1],a[i]));
		return solve(now->ch[0])+solve(now->ch[1])+mi+(1<<now->dep);
	}
	if(now->ch[0])return solve(now->ch[0]);
	if(now->ch[1])return solve(now->ch[1]);
	return 0;
}

int main()
{
    
    
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	sort(a+1,a+n+1);root=new node(29);
	for(int i=1;i<=n;i++)insert(i);
	printf("%lld",solve(root));
}

おすすめ

転載: blog.csdn.net/a_forever_dream/article/details/108239800