zoukankan      html  css  js  c++  java
  • CodeForces #367 div2 D Trie

    题目链接:Vasiliy's Multiset

    题意:这里有一个set容器,有三种操作,+ num, - num, ? num,分别代表往容器里加上num,或者拿走num,或着从容器里找一个数temp使得temp^num的值最大。输出这个最大值。

    思路:对于XOR操作,一般都要拆位考虑,拆完之后用Trie或者线段树维护,然后,这个题把每个数的二进制30位(前面不够的用0补全)插入Trie,查询的时候,对于每一位先尝试往相反的方向走,因为异或 只要越高位

    相反值越大,然后再尝试往相同的方向走。最后如果没有找到这个数的话,ans即为该数字本身,因为0一直在容器里。

    tree[maxn][2],maxn应为n*30,因为一个数字占30个节点,总结点数不会超过n*30.

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #define maxn 200010*30
    using namespace std;
    
    int tree[maxn][2]; // Trie
    int cnt[maxn]; // 每个节点的经过次数
    int val[maxn]; //以每个节点为终点的数字
    int tot; // 每个节点的编号
    int num;
    int now[30]; // 保存每个数字的30位
    
    void update(int x, int type) {
        int rt = 0; // 插入当前数字时的地址
        num = 0;
        int t = x;
        memset(now, 0, sizeof(now));
        while(t) {
            now[num++] = t%2;
            t /= 2;
        }
        for (int i=29; i>=0; --i) {
            int temp = now[i];
            cnt[rt] += type;
            if (!tree[rt][temp]) {
                tree[rt][temp] = tot++;
            }
            rt = tree[rt][temp];
        }
        cnt[rt] += type;
        val[rt] = x;
    }
    
    int query(int x) {
        int t = x;
        int rt = 0;
        num = 0;
        memset(now, 0, sizeof(now));
        while(t) {
            now[num++] = t%2;
            t /= 2;
        }
        int ans = 0;
        for (int i=29; i>=0; --i) {
            int temp = now[i];
            if ((tree[rt][temp^1]) && cnt[tree[rt][temp^1]]) {
                rt = tree[rt][temp^1];
            }
            else if ((tree[rt][temp]) && cnt[tree[rt][temp]]) {
                rt = tree[rt][temp];
            }
            else {
                ans = -1;
                break;
            }
        }
        if (ans != -1) {
            ans = max(val[rt]^x, x);
        }
        else ans = x;
        return ans;
    }
    
    
    int main() {
       // freopen("in.cpp", "r", stdin);
        int n;
        while(~scanf("%d", &n)) {
            tot = 1;
            memset(tree, 0, sizeof(tree));
            memset(cnt, 0, sizeof(cnt));
            memset(val, -1, sizeof(val));
    
            for (int i=0; i<n; ++i) {
                char op;
                int temp;
                getchar();
                scanf("%c%d", &op, &temp);
                //cout << op << "==" << temp << endl;
                if (op == '+') {
                    update(temp, 1);
                }else if (op == '-') {
                    update(temp, -1);
                }else {
                    int ans = query(temp);
                    printf("%d
    ", ans);
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    html float
    HTML:scrollLeft,scrollWidth,clientWidth,offsetWidth之完全详解
    FLEX 如何跳出警告对话框 Alert
    点击超链接,不改变滚动条位置
    HTML DOM CSS position的用法
    FLEX 动态添加事件
    html display
    php和swf通信
    html css float left与 float right的使用说明
    如何去除FLEX LINECHART 线条阴影
  • 原文地址:https://www.cnblogs.com/icode-girl/p/5774154.html
Copyright © 2011-2022 走看看