• trie树——【吴传之火烧连营】


    突然发现好像没有讲过一种叫做tire树的神奇东西。

    问题描述:

    题目描述

    【题目背景】

    蜀汉章武元年(221年),刘备为报吴夺荆州、关羽被杀之仇,率大军攻吴。吴将陆逊为避其锋,坚守不战,双方成对峙之势。蜀军远征,补给困难,又不能速战速决,加上入夏以后天气炎热,以致锐气渐失,士气低落。刘备为舒缓军士酷热之苦,命蜀军在山林中安营扎寨以避暑热。陆逊看准时机,命士兵每人带一把茅草,到达蜀军营垒时边放火边猛攻。蜀军营寨的木栅和周围的林木为易燃之物,火势迅速在各营漫延。蜀军大乱,被吴军连破四十余营。陆逊火烧连营的成功,决定了夷陵之战蜀败吴胜的结果。

    【问题描述】

    刘备带兵深入吴境,陆逊却避而不出,蜀军只得在山林中安营扎寨。而刘备在扎营时却犯了兵家大忌,将兵营排列成一条直线,远远看去,就像是一条串着珠子的链,美其名曰:链寨。如果吴军将领是一般人,那么这也许不算什么,而陆逊何许人也,他可是江东才子,能力不低于周瑜的一代儒将。他看到刘备这样排阵,心生一计,决定用火攻破阵。然而,火计除了要有风,选定引火点也非常重要,对于刘备的布阵,最佳引火点一定是n个兵营中的一个。而因为风水轮流转,每天的最佳引火点都不一样。我们给每个兵营定下一个固定不变的火攻值Ai,每天定下一个风水值K,对于每天的最佳引火点,显然是所有兵营中火攻值与风水值异或的结果最大的那一个兵营。然而,陆逊是个谨慎的人,他要观察时机,在m天中选定一个最佳的进攻的日期,为此他演算出了这m天每天的风水值,然后他希望你能够告诉他这m天每天最佳引火点的兵营编号。

    输入

    第一行n,m,代表有n个兵营,m天。

    接下来一行有n个非负整数,代表这n个兵营的火攻值。

    接下来一行有m个非负整数,代表这m天的风水值。

    输出

    输出共m行,每行输出一个整数,代表第m天最佳引火点的编号。

    如果存在多个最佳引火点使得火攻值与风水值的异或值最小,请任意输出一组解即可。

    样例输入

    3 2
    1 2 3
    4 5

    样例输出

    3 2

    提示

    【样例解释】

    对于第1天,由于4 xor 1=5, 4 xor 2=6, 4 xor 3=7,选择第3个引火点是最佳的。

    对于第2天,由于5 xor 1=4, 5 xor 2=7, 5 xor 3=6,选择第2个引火点是最佳的。

    【数据规模和约定】

    对于30%数据,n<=1000,m<=1000

    对于100%数据,n<=100000,m<=100000, 0<=k,ai<=2147483647

    思路分析:

    这是一道非常经典的trie树的题。那么trie树又是什么神奇东西呢?

    假设我们有两个字符串abcba,abcac,我们可以把它放到一颗树上,这棵树的节点是字符串中的字母,字符串中的每以为都在树上代表了一层,这棵树的点并不是一开始就有的,而是我们通过不断添加字符串来拓展的。比如上面两个字符串,我们先将第一个字符串加入tire树,那么就构建出了一个5层的树第1层有一个节点a,第2层有一个节点b,第3层有一个节点c,第4层有一个节点b,第5层有一个节点a。那么我们应该如何加入abcac,对于第1个字符a,我们发现它已经在trie树中了,那么就走到第1层的节点a上,一直到字符c,我们都能这么做,但是第4个字符a,我们发现第3层的c节点的连边只有b而没有a,那么我们便在第四层新加入一个节点a,并将它和第三层的c节点连一条边,第5个字符b也是如此。

    那么这题应该如何来做呢?

    类似的,把读入的数的二进制加入trie树中,那么询问时,我们要尽量的走与询问数的二进制相反的点,因为这样异或之后就可以让那一位变成1,很简单不是吗?

    代码实现:

    var
      map:array[1..8000000,0..1]of longint;
      flag:array[1..8000000]of longint;
      a:array[0..32]of 0..1;
      i,j,k,n,m,x,tot:longint;
    procedure add(x:longint);
    var
      i,u:longint;
    begin
      u:=1;
      for i:=1 to 32 do
        if map[u,a[i]]=0 then begin inc(tot); map[u,a[i]]:=tot; u:=tot; end
          else u:=map[u,a[i]];
      flag[u]:=x;
    end;
    function find:longint;
    var
      i,u:longint;
    begin
      u:=1;
      for i:=1 to 32 do
        if map[u,a[i]]=0 then u:=map[u,1-a[i]] else u:=map[u,a[i]];
      exit(flag[u]);
    end;
    begin
      read(n,m);
      tot:=1;
      for i:=1 to n do
      begin
        read(x);
        fillchar(a,sizeof(a),0);
        k:=32;
        while x>0 do
        begin
          a[k]:=x mod 2;
          x:=x div 2; dec(k);
        end;
        add(i);
      end;
      for i:=1 to m do
      begin
        read(x);
        k:=32;
        for j:=1 to 32 do a[j]:=1;
        while x>0 do
        begin
          a[k]:=1-(x mod 2);
          x:=x div 2; dec(k);
        end;
        writeln(find);
      end;
    end.
  • 相关阅读:
    Python round() 函数
    Python pow() 函数
    图像角点检测
    计算机视觉解析力
    空间点像素索引(三)
    空间点像素索引(二)
    空间点像素索引(一)
    相机标定实用方案
    摄像头的主要参数
    多篇开源CVPR 2020 语义分割论文
  • 原文地址:https://www.cnblogs.com/WR-Eternity/p/9849801.html
Copyright © 2020-2023  润新知