1. 程式人生 > 其它 >CF817E Choosing The Commander 題解

CF817E Choosing The Commander 題解

有Q次操作,每次操作有三種類型,分別是 > 1 pi 把 pi 加入集合 S > 2 pi 把 pi 從集合 S 中刪除 > 3 pi li 表示查詢集合中有多少個元素異或上 pi 後 小於 li

有Q次操作,每次操作有三種類型,分別是

1 pi 把 pi 加入集合 S
2 pi 把 pi 從集合 S 中刪除
3 pi li 表示查詢集合中有多少個元素異或上 pi 後 小於 li

0/1trie樹.顯然對於每一位,若這一位異或後比li的這一位小,那麼該結點所在的子樹異或後都必然小於li,而若與li的這一位相等,則向這邊迭代.

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 3000005;
int n, tot = 1;
int val[N], tree[N][2];
void add(int k, int v)
{
    int now = 1;
    for (int i = (1 << 30); i; i >>= 1)
    {
        val[now] += v;
        bool temp = k & i;
        if (!tree[now][temp])
            tree[now][temp] = ++tot;
        now = tree[now][temp];
    }
    val[now] += v;
}
int query(int v, int l)
{
    int now = 1, ans = 0;
    for (int i = (1 << 30); i; i >>= 1)
    {
        bool temp1 = v & i, temp2 = l & i;
        if (temp1 < temp2)
            ans += val[tree[now][0]];
        if (temp1 && temp2)
            ans += val[tree[now][1]];
        if (temp2)
            now = tree[now][temp1 ^ 1];
        else
            now = tree[now][temp1];
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        if (x == 1)
        {
            int v;
            cin >> v;
            add(v, 1);
        }
        if (x == 2)
        {
            int v;
            cin >> v;
            add(v, -1);
        }
        if (x == 3)
        {
            int v, l;
            cin >> v >> l;
            cout << query(v, l) << endl;
        }
    }
}

本文來自部落格園,作者:Kinuhata,轉載請註明原文連結:https://www.cnblogs.com/KinuhataSaiai/p/15550664.html