Perfect Security problem solution CF923C []

First unscrupulous propaganda about the blog wwwwww
Article list - nuclear fusion reactor core - Luo Gubo off


Knowledge Point: Trie tree / tree dictionary / greedy

  • Meaning of the questions:

(Abridged version of casual working too Kichiku a)

There \ (a, b \) two of length \ (n-\) is the number of columns,
the \ (B \) series rearrange,
then \ (a, b \) corresponding to the position number of phases \ (\ underline {\ XOR text {}} \) ,
to give a new series \ (C \)

You can find a new series \ (C \) \ (\ underline {\ lexicographically smallest text {}} \) scheme
, and outputs the result of this program

\(1\leqslant N \leqslant 3e5\)
\(\underline{a[i],b[i] \leqslant 2^{30}}\)


  • Analysis of the meaning of problems:

    • Lexicographically smallest:
      the \ (C \) each position of the number of columns \ (C [I] \) ,
      should be able to reach the minimum value
      can be considered greedy

    • XOR, \ (A [I], B [I] \ leqslant 2 ^ {30} \) :
      ? Why the data range to be written like this
      consider ... XOR operation
      occur binary split

      The \ (a [i], b [i] \) after the split, greedy can easily
      enumerate two \ (01 \) number on the strings every
      try to make different or after you as \ ( 0 \)
      to select the most appropriate \ (b [i] \)

    • What used to maintain binary number after the split?
      Binary numbers can be
      treated as a string to handle
      expect to establish a dictionary tree
      because only \ (0 \) two characters, it is a binary tree
      based on the nature of the dictionary tree,
      you can completion of the operation easily.


  • Algorithm:

    Based on the respective first establish a \ (b [i] \) of the binary trie
    and record the number of elements in each node represents occurring \ (CNT \)

    Each query operation, the \ (a [i] \) for the parameters passed
    from the dictionary root portion, start looking down,
    to find each layer (i.e., each bit) elements,
    as much as possible so that \ (a [i ], b [i] \) this bit is XORed \ (0 \)
    if the number of this element in the optimum position \ (0 \) , select another element
    number of the selected element so that this position \ (--1 \)
    and go to the next level and continue to find it.

    Depending on the nature of the dictionary tree,
    each query operations are necessarily can be found,
    a local optimum to meet the most suitable \ (a [i] \) a \ (b [i] \)
    Query \ (\ n-) after the time, i.e., You can find the best answer

  • Note specific point:

    To facilitate the operation,
    to ensure that the dictionary tree,
    binary numbers stored in the forward

    That is,
    if using bitwise binary split
    first upper split out, and then split the low
    Refer to code


attach Ugly Code:

#include<cstdio>
#include<ctype.h>
#include<algorithm>
#define int long long
//==================================================
const int MARX = 3e5+10;
struct node
{
    int cnt,son[2];//存每个节点代表元素出现次数 , 两儿子 
}trie[20*MARX];
int n,num=1;
int a[MARX],b[MARX];//原始数列 
//==================================================
inline int read()
{
    int fl=1,w=0;char ch=getchar();
    while(!isdigit(ch) && ch!='-') ch=getchar();
    if(ch=='-') fl=-1;
    while(isdigit(ch)){w=w*10+ch-'0',ch=getchar();}
    return fl*w;
}
inline void insert(int key)//建树 
{
    int now=1;//从根节点开始,向下查找 
    trie[1].cnt++;
    for(int i=30;i>=0;i--)//将二进制数正向加入字典树 
    {
        int next=(key>>i)&1; //当前位数 
        if(!trie[now].son[next]) trie[now].son[next]= ++num;//添加新节点 
        now=trie[now].son[next];
        trie[now].cnt++;//增加出现次数 
    }
}
inline int query(int key)//回答询问 
{
    int now=1,ans=0;//从根部查找 
    for(int i=30;i>=0;i--) 
    {
        int next=(key>>i)&1;//最优情况 
        if(!trie[trie[now].son[next]].cnt) next=(!next);//不能满足最优情况 
        ans=(ans<<1)+next;//更新找到的 b[i] 
        now=trie[now].son[next];
        trie[now].cnt--;//减少出现次数 
    }
    return ans^key;
}
//==================================================
signed main()
{
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=n;i++) b[i]=read(),insert(b[i]); 
    for(int i=1;i<=n;i++) printf("%lld ",query(a[i]));
}

Guess you like

Origin www.cnblogs.com/luckyblock/p/11456323.html