01 字典树模板 求XOR最大值

来源:互联网 发布:怎么优化 编辑:程序博客网 时间:2024/05/18 01:36

//注意思想是用01字符串进行建树, 然后去匹配, 并且一定要是从高位到低
//位进行建树, 因为我们当前用的是贪心策略, 尽量让高位得到的XOR值最
//大, 所以从高位到低位建树.
模板题

const int ssize = 33;int cas=1;int n,m;struct node{    node *next[2];    int val;    node():val(0){        memset(next,NULL,sizeof(next));    }};node *root;void build(int n){    bitset<ssize> bit = n;    node *Tree = root;    for(int i=32;i>=0;i--){        int k = bit[i];        if(!Tree->next[k]){            node *one = new node();            Tree->next[k] = one;            Tree = one;        }        else Tree = Tree->next[k];    }    Tree->val = n;   //把路的终点设置成该条路是那个数的.}int query(int n){    bitset<ssize> bit = n;    node *Tree = root;    for(int i=32;i>=0;i--){        int k = bit[i];        if(Tree->next[k^1]){   //如果有相反的点就走相反的.            Tree = Tree->next[k^1];        }        else Tree = Tree->next[k];  //否则就只能继续往前走.    }    return Tree->val;   //返回走的那条路的终点的值.}void solve(){    root = new node();    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++){        int u;        scanf("%d",&u);        build(u);   //把输入的数进行建树.    }    printf("Case #%d:\n",cas++);    for(int i=0;i<m;i++){        int u;        scanf("%d",&u);        printf("%d\n",query(u));   //询问数.    }}int main(){    int t = 1;    cin >> t;    while(t--){        solve();    }}

带删除的01字典树, 其实就是增加了一个计数器, 删掉这个节点其实就是将这个节点处的计数器–, 在询问的时候, 判一下是否这个计数器是否大于零就是了.
//注意就是当前指针所指的位置, 还有就是它一来就询问, 因为此时字典树中还有路可走, 所以必须实现先建一条0的路给它走.
传送门
AC Code

/** @Cain*/const int ssize = 33;int cas=1;int n;struct node{    node *next[2];    int val;    int cnt;    node():val(0),cnt(0){        memset(next,NULL,sizeof(next));    }};node *root;void build(int n){    bitset<ssize> bit = n;    node *Tree = root;    for(int i=32;i>=0;i--){        int k = bit[i];        if(!Tree->next[k]){            node *one = new node();            Tree->next[k] = one;            Tree = one;            Tree->cnt++;   //注意计数器的位置.先移动下来, 在让计数器++.        }        else{            Tree = Tree->next[k];            Tree->cnt++;        }    }    Tree->val = n;    Tree->cnt++;}int query(int n){    bitset<ssize> bit = n;    node *Tree = root;    for(int i=32;i>=0;i--){        int k = bit[i];        if(Tree->next[k^1] && Tree->next[k^1]->cnt >0){            Tree = Tree->next[k^1];   //注意计数器的位置.一定是下一步所要走的那个节点的计数器.        }        else Tree = Tree->next[k];    }    return Tree->val;}void del(int n){    bitset<ssize> bit = n;    node *Tree = root;    for(int i=32;i>=0;i--){        int k = bit[i];        Tree = Tree->next[k];        Tree->cnt--;    }    Tree->cnt--;}void solve(){    root = new node();    scanf("%d",&n);    int k;    build(0);   //有可能最先就询问, 所以需要先建一个0的路. 否则就会RE!    while(n--){        char op[10] = {0};        scanf("%s",op);        scanf("%d",&k);        if(op[0] == '+'){            build(k);        }        else if(op[0] == '-'){            del(k);        }        else{            printf("%d\n",query(k)^k);        }    }}int main(){    int t = 1;    //cin >> t;    while(t--){        solve();    }}