D. Vasiliy's Multiset (字典树)

  • 题目链接:http://codeforces.com/contest/706/problem/D
  • 题意:对一个集合有三种操作:
    • “+ x” 在这个集合中加入x
    • “- x” 在这个集合中删除x(保证原本的集合中有x)
    • “? x” 求x与集合中的某个数异或后的最大值
  • 思路:可以用字典树查询从高位到低位,尽可能查到与x异或后能让当前2进制位为1的数位。其累加即为结果。
  • 算法:字典树

#include <bits/stdc++.h>
#define pi acos(-1)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 6000000 + 10;
const int mod = 1e9 + 7;

char opt[10];
int sz = 1;

struct Node
{
    int next[5], hcnt;
    Node(){
        hcnt=0;
        memset(next, 0, sizeof(next));
    }
}Trie[maxn];

void _insert(int x)
{
    int u=0, pos;
    for(int i=30; i>=0; i--){
        pos = x&(1<<i)?1:0;
        if(Trie[u].next[pos] == 0) Trie[u].next[pos] = sz++;
        u = Trie[u].next[pos];
        Trie[u].hcnt++;
    }
}

void _delete(int x)
{
    int u=0, pos;
    for(int i=30; i>=0; i--){
        pos = x&(1<<i)?1:0;
        u = Trie[u].next[pos];
        Trie[u].hcnt--;
    }
}


void _search(int x)
{
    int u=0, pos, res=0, tmp;
    for(int i=30; i>=0; i--){
        pos = x&(1<<i)?0:1;
        tmp = Trie[u].next[pos];
        if(tmp && Trie[tmp].hcnt){
            res += pow(2, i);
            u = tmp;
        }
        else { u = Trie[u].next[!pos]; }
    }
    printf("%d\n", res);
}


int main()
{
    int q, x;
    scanf("%d", &q);
    _insert(0);
    while(q--){
        scanf("%s%d", opt, &x);
        if(opt[0] == '+') _insert(x);
        else if(opt[0] == '-') _delete(x);
        else if(opt[0] == '?') _search(x);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37352710/article/details/81257395