HDU4825_01辞書ツリー
11344 ワード
01ディクショナリ・ツリーは、通常のディクショナリ・ツリーの変形であり、主に2つの数の最大異または値の問題を処理するために使用されます.
まず、普通の辞書の木を01辞書の木にする方法を自分で考えてみましょう.一般辞書ツリーに格納文字、例えば26文字の辞書ツリーが26フォークツリー、01辞書ツリーが01、明らかに二フォークツリー である. int型を格納01ディクショナリツリーは最大32層(第1層が通常のディクショナリツリーに類似してルートノードであり、何も格納されていない) である. 01ディクショナリツリーは、実は整数データをバイナリに変換し、数のリーフノードはバイナリの最低ビットを格納し、ルートノードに近づくほど格納ビット数が高くなる.
最大の異或を解決するには、対応するビットの異なる分岐を貪欲に探せばいい.
例題HDU 4825はあなたにn個の数をあげて、更にm回の問い合わせを与えて、毎回尋ねることに対して、1つの値xを与えて、あなたにn個の数の中で1つの数を探し当てて、xと異なってあるいは値が最大です
では、まずn個の数に木を建てて、尋ねるたびに貪欲に探せばいいのです.
tips:ツリー削除操作については、すべての配列を直接初期化することと、ルートノードのみを初期化することと、2回目の作成中に初期化することと、ツリー削除操作の頻度を選択することができます.
ACコード:
まず、普通の辞書の木を01辞書の木にする方法を自分で考えてみましょう.
最大の異或を解決するには、対応するビットの異なる分岐を貪欲に探せばいい.
例題HDU 4825はあなたにn個の数をあげて、更にm回の問い合わせを与えて、毎回尋ねることに対して、1つの値xを与えて、あなたにn個の数の中で1つの数を探し当てて、xと異なってあるいは値が最大です
では、まずn個の数に木を建てて、尋ねるたびに貪欲に探せばいいのです.
tips:ツリー削除操作については、すべての配列を直接初期化することと、ルートノードのみを初期化することと、2回目の作成中に初期化することと、ツリー削除操作の頻度を選択することができます.
ACコード:
#include
using namespace std;
#define IOS \
ios::sync_with_stdio(false); \
cin.tie(0); \
cout.tie(0);
#define ll long long
ll z_o_trie[32000000][2];
ll value[32000000];
ll cnt = 1;
void Insert(ll a)
{
ll p = 0;
for (ll i = 31; i >= 0; i--)
{
ll temp = (a >> i) & 1;
if (z_o_trie[p][temp])
p = z_o_trie[p][temp];
else
p = z_o_trie[p][temp] = cnt++;
}
value[p] = a;
}
ll get(ll a)
{
ll p = 0;
for (ll i = 31; i >= 0; i--)
{
ll temp = (a >> i) & 1;
if (z_o_trie[p][temp ^ 1])
p = z_o_trie[p][temp ^ 1];
else
p = z_o_trie[p][temp];
}
return value[p];
}
void init()
{
cnt = 1;
fill(z_o_trie[0], z_o_trie[0] + 1000000 * 2, 0);
fill(value, value + 1000000, 0);
}
int main()
{
IOS;
ll t;
cin >> t;
ll CASE = 1;
while (t--)
{
cout << "Case #" << CASE++ << ":" << endl;
init();
ll n, m;
cin >> n >> m;
for (ll i = 1; i <= n; i++)
{
ll temp;
cin >> temp;
Insert(temp);
}
for (ll i = 1; i <= m; i++)
{
ll temp;
cin >> temp;
cout << get(temp) << endl;
}
}
return 0;
}