最小异或对

题意:

给出一个多重集合,每次可以加一个数,删一个数,或者询问从集合中选出两个数,使其异或和最小。
输出每个询问的答案。

Solution:

维护一个字典树,对于每个节点我们维护三个值:
1.该节点子树内的答案
2.子树内的元素的个数
3.如果子树内只有一个元素,记录其值

const int N = 2e5 + 50; 
const int M = N << 1;
const int mod = 1e9 + 7;

struct Info {
    int ans, val, cnt;
    Info() : ans(inf), cnt(0), val(-1) {}
    Info(int x) : ans(inf), cnt(1), val(x) {}
    Info(int ans, int val, int cnt) : ans(ans), val(val), cnt(cnt) {}
}tr[N * 32];

Info operator+ (const Info &a, const Info &b) {
    Info res = Info();
    res.cnt = a.cnt + b.cnt;
    res.ans = min(a.ans, b.ans);
    if(res.cnt == 1) res.val = a.cnt ? a.val : b.val;
    if(a.cnt == 1 && b.cnt == 1) res.ans = a.val ^ b.val;
    return res;
}

int son[N * 32][2];
int idx = 1;

void insert(int u, int x, int dep) {
    if(dep == -1) {
        tr[u].cnt++;
        if(tr[u].cnt == 1) tr[u] = Info(x);
        if(tr[u].cnt >= 2) tr[u].ans = 0;
        return;
    }
    int bit = x >> dep & 1;
    if(!son[u][bit]) son[u][bit] = ++idx;
    insert(son[u][bit], x, dep - 1);
    tr[u] = tr[son[u][0]] + tr[son[u][1]];
}
void del(int u, int x, int dep) {
    if(dep == -1) {
        tr[u].cnt--;
        if(tr[u].cnt == 0) tr[u] = Info();
        if(tr[u].cnt == 1) tr[u] = Info(inf, x, 1);
        return;
    }
    int bit = x >> dep & 1;
    del(son[u][bit], x, dep - 1);
    tr[u] = tr[son[u][0]] + tr[son[u][1]];
}
signed main() {
#ifdef JANGYI
    freopen("input.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif

    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    

    int n;
    cin >> n;
    while(n--) {
        string s;
        cin >> s;
        if(s[0] == 'A') {
            int x;
            cin >> x;
            insert(1, x, 29);
        } else if(s[0] == 'D') {
            int x;
            cin >> x;
            del(1, x, 29);
        } else {
            cout << tr[1].ans << '\n';
        }
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值