字典树!

A - Xor Sum

Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么? 

Input输入包含若干组测试数据,每组测试数据包含若干行。 
输入的第一行是一个整数T(T < 10),表示共有T组数据。 
每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。Output对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。 
对于每个询问,输出一个正整数K,使得K与S异或值最大。Sample Input

2
3 2
3 4 5
1
5
4 1
4 6 5 6
3

Sample Output

Case #1:
4
3
Case #2:
4
调了一下午的程序!太snake了! 这个字典树建树是好建的,但是查询就很烦了。
首先,数字默认的整数类型是longint,所以你1<<32 会爆longint(1<<32=1)(1<<31=-maxlongint),那怎么做?令(int64)k=1,k<<32,
就不会爆了

其次在用function 的时候,每一层都会返回一个值!如果你不手动让它返回一个值,那它就会自作主张地随机返回一个值,得到的答案就是错的!
(经检验,procedure 不会有这种情况发生,只要不死循环)
另外,数组大小要计算好,每个数字最大32位,<n*32 的空间要开,尽量开大点空间,在不爆的前提下!
 1 var
 2 l,t,i:longint;
 3 tree:array[0..2000005,0..1]of int64;
 4 
 5 x,y,tot,n,m,ans:int64;
 6 procedure insert(u:int64);
 7  var i:longint; val,now,k:int64;
 8   begin
 9   now:=0; val:=0;
10 
11   for i:=32 downto 0 do
12    begin
13    k:=1;    k:=k<<i;
14     if  (k and u)<>0 then val:=1 else val:=0;
15     if  tree[now,val]=-1 then
16      begin
17        inc(tot);
18        tree[now,val]:=tot;
19      end;
20      now:=tree[now,val];
21    //  inc(num[now]);
22    end;
23 
24  end;
25  function find(i,now,u:int64):int64;
26    var k,tmp:int64;
27  begin
28    //writeln(i ,' ',ans);
29   if i<0 then exit(ans);
30   k:=1; k:=k<<i;
31        if (k and u)<>0 then
32         begin
33         // writeln(((1<<i)and u));
34           if tree[now,0]<>-1 then
35           begin
36         //  if tree[now,0]<>0 then   ans:=ans+k;
37             tmp:=find(i-1,tree[now,0],u);
38           end
39            else
40            begin
41              ans:=ans+k;
42              tmp:=find(i-1,tree[now,1],u);
43            end;
44         end else
45           if (k and u)=0 then
46            if tree[now,1]<>-1 then
47             begin
48               ans:=ans+k;
49               tmp:=find(i-1,tree[now,1],u);
50             end
51            else
52              begin
53               // ans:=ans+tree[now,0]>>i;
54                tmp:=find(i-1,tree[now,0],u);
55              end;
56     exit(tmp);//使每层都有返回值的操作
57   end;
58 begin
59 readln(t);
60 for l:=1 to t do
61 begin
62 fillchar(tree,sizeof(tree),255);
63 tot:=0;
64 readln(n,m);
65  for i:=1 to n do
66  begin
67     read(x);
68     insert(x);
69  end;
70   writeln('Case #',l,':');
71  for i:=1 to m do
72   begin
73     readln(y);
74     ans:=0;
75 
76     writelN(find(32,0,y));
77   end;
78 end;
79 end.

NOIP2018 rp++
原文地址:https://www.cnblogs.com/brilliant107/p/9449970.html