タイトルリンク
ボーイフレンド自動質問機の最初の質問
オリジナルのアイデア:
もともとはバイナリのa配列から辞書ツリーを作成し、最適なマッチングのためにb配列を使用したかったのですが、繰り返しの問題への対処方法が思いつきませんでした。
後で:
kan、wan、およびtiをしばらくすると、私はこれを見つけました。
バイナリに従って2つの配列に対して2つの辞書ツリーaとbをそれぞれ構築し、各検索に対して最適なマッチングを実行します。
コードを詳しく見る
#include <bits / stdc ++。h> using namespace std; const int maxn = 3e6 + 10 ; #define ios std :: ios :: sync_with_stdio (false) struct node { int ci、di [ 2 ]; /// cは現在のポイントが使用される回数di は、現在のビットが0と1である添え字を格納します}; ノードtreea [maxn]、treeb [maxn]; /// 2つのツリー int cnta、cntb; /// 2つのツリー void init()の最大添え字()/// 初期化 { for(int i = 0 ; i <= cnta; i ++ ){ treea [i] .ci= 0 ; treea [i] .di [ 0 ] = treea [i] .di [ 1 ] = 0 ; } for(int i = 0 ; i <= cntb; i ++ ){ treeb [i] .ci = 0 ; treeb [i] .di [ 0 ] = treeb [i] .di [ 1 ] = 0 ; } } void insert1(int a) { int dir = 1 ; /// 初始坐标 for(int i = 32 ; i> =0 ; i- ){ int t =(a >> i&1 ); if(treea [dir] .di [t] == 0){ /// 現在のビットがtの場合、 treea [ dir] .di [t] = ++ cnta; } dir = treea [dir] .di [t]; /// この座標に変更 treea [dir] .ci ++; /// 使用度+ 1 } } void insert2(int b)/// Ibid。 { int dir = 1 ; for(int i = 32 ; i> = 0; i- ){ int t =(b >> i&1 ); if(treeb [dir] .di [t] == 0 ){ treeb [dir] .di [t] = ++ cntb; } dir = treeb [dir] .di [t]; treeb [dir] .ci ++ ; } } int get_ans() { int ca = 1、cb = 1 ; /// 两个初始坐标 int ans = 0 ; for(int i = 32 ; i> = 0 ; i --){ int zeroa = 0 , zerob = 0 , onea = 0 , oneb = 0 ;///当前为01是否有使用度 if(treea[ca].di[0] != 0 && treea[treea[ca].di[0]].ci > 0)zeroa = 1; if(treea[ca].di[1] != 0 && treea[treea[ca].di[1]].ci > 0)onea = 1; if(treeb[cb].di[0] != 0 && treeb[treeb[cb].di[0 ]]。ci> 0)zerob = 1 ; if(treeb [cb] .di [ 1 ]!= 0 && treeb [treeb [cb] .di [ 1 ]]。ci> 0)oneb = 1 ; if(onea && oneb){ ca = treea [ca] .di [ 1 ]; cb = treeb [cb] .di [ 1 ]; } else if(zeroa && zerob){ ca = treea [ca] .di [ 0 ]; cb = treeb [cb] .di [ 0 ]; } else if(zeroa && oneb){ ca = treea [ca] .di [ 0 ]; cb = treeb [cb] .di [ 1 ]; ans + =(1 << i); } else if(zerob && onea){ ca = treea [ca] .di [ 1 ]; cb = treeb [cb] .di [ 0 ]; ans + =(1 << i); } treea [CA] .ci - 。 treeb [CB] .ci - 。 } ansを 返します。 } int a [maxn]、b [maxn]、c [maxn]; 署名されたmain() { ios; cin.tie(0); /// int t; cin >> t; while(t- ) { int n; cin >> n; cnta = 1 ; cntb = 1 ; for(int i = 1 ; i <= n; i ++)cin >> a [i]、insert1(a [i]); for(inti = 1 ; i <= n; i ++)cin >> b [i]、insert2(b [i]); for(int i = 1 ; i <= n; i ++ ){ c [i] = get_ans(); } sort(c + 1、c + 1 + n); for(int i = 1 ; i <= n; i ++ ){ cout << c [i]; if(i!= n)cout << ' ' ; } cout << ' \ n'; 初期化(); } 0を返し ます。 }