题目链接: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\n", ans);
            }
        }
    }
    return 0;
}

 

posted on 2016-08-15 19:49  小小八  阅读(120)  评论(0编辑  收藏  举报