Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset (TireTree之位字典树)

题目链接:http://codeforces.com/contest/706/problem/D

题意:

对一个multiset(集合中的元素可以重复的set)有三种操作——

+ x: 增加元素x

- x: 减少元素x

?x: 求multiset中与x抑或得到的数最大为多少

已知0总是存在于multiset中。

 

分析:

时限为4s。

1 ≤ xi ≤ 109,由于109≈(2103≈230,103<210,也就是说x最多为30位

那么对数的每一位建立字典树,即最多为30层。

当要找与x抑或得到的结果最小的数时,只需尽可能找与x的每个数位相反的路径,

即可得到multiset中的那个数。

 

这样每个数都按照最大数可能的位数30来构建字典树,方便处理。

#include<cstdio>
#include<algorithm>
#include<map>
#include<cstring>
#include<string>
#include<iostream>
#include<set>
#include<vector>
#include<cmath>

using namespace std;

typedef long long ll;
const int mod = 1000000007;
const int maxn = 200010;
const int len = 30;

struct node
{
    int cnt;
    int next[2];
}tree[maxn*len];

int num;

void init()
{
    memset(tree,-1,sizeof(tree));
    num = 0;
}
void add(int x)
{
    int now = 0;
    bool k;
    for(int i=len-1;i>=0;i--)
    {
        k = (x>>i)&1;
        if(tree[now].next[k]==-1)
            tree[now].next[k] = ++num;
        now = tree[now].next[k];
        tree[now].cnt = tree[now].cnt==-1?1:(tree[now].cnt+1);
    }
}

void del(int x)
{
    int now = 0;
    bool k;
    for(int i=len-1;i>=0;i--)
    {
        k = (x&(1<<i));
        now = tree[now].next[k];
        tree[now].cnt--;
    }
}

int query(int x)
{
    int now = 0,ret = 0;
    bool k;
    for(int i=len-1;i>=0;i--)
    {
        k = (x&(1<<i));
        if(tree[now].next[!k]!=-1 && tree[tree[now].next[!k]].cnt>0)
            k = !k;
        now = tree[now].next[k];
        ret = ret|(k<<i);
    }
    return ret;
}

int main()
{
    int q;
    char op[2];
    int x;
    while(~scanf("%d",&q))
    {
        init();
        add(0);
        for(int i=0;i<q;i++)
        {
            scanf("%s%d",op,&x);
            if(op[0]=='+')
                add(x);
            else if(op[0]=='-')
                del(x);
            else
            {
                int t = query(x);
                printf("%d\n",(t^x));
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2016-08-13 17:32  fukan  阅读(164)  评论(0编辑  收藏  举报