E. Choosing The Commander
题意:
q次询问(q<=1e5)每次询问对应三种操作中的一种
1 x 增添一个数x
2 x 删除一个数x
3 x l 询问现有的数中 异或上x的值小于l的个数
思路:
询问次数1e5 普通暴力每次遍历查找复杂度为On2 会TLE
故要想一个更优的方法
字典树 复杂度:Onlogn
对于每个增添的数 将其转换为二进制数 然后用字典树维护二进制01串
插入一个数:
每一个数的二进制数代表一条延续下来的路径 就从高位到低位添加 如果延续下来的当前位上有路径 直接让对应的cnt增加 否则 新添一个节点
删除一个数:
直接将x对应的每位的0或1的cnt减少
询问一个数:
x l 记录x 和 l对应二进制位位上的数 记为 bit1 bit2 字典树上的数该位上是 bit
1. 如果 bit2 == 0:
若 bit1 == 0 :bit == 0 bit1 ^ bit == bit2就继续寻找下一位
bit == 1 1 ^ 0 = 1 > 0 不符合了不能继续
若 bit1 == 1 : bit == 0 bit1 ^ bit > bit2 不符合了不能继续
bit == 1 bit1 ^ bit == bit2 继续找下一位
2. 如果bit2 == 1:
若bit1 == 0 : bit == 0 bit1 ^ bit < bit2 满足 该节点0的个数贡献给答案
bit == 1 bit1 ^ bit == bit2就继续寻找下一位
若 bit1 == 1 : bit == 0 bit1 ^ bit == bit2 就继续寻找下一位
bit == 1 bit1 ^ bit < bit2 满足 该节点0的个数贡献给答案
#include<bits/stdc++.h> #define ll long long #define ull unsigned long long #define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); using namespace std; const ll inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; const double eps = 1e-4; const int N = 1e6 + 5; const int M = 1e5 + 5; const int mod = 1e9 + 7; int n, a[N], x, op, l; //cnt储存当前节点0 和 1的个数 //son储存当前节点的子节点的编号 struct node { int cnt[2] = { 0 }; int son[2] = { 0 }; }tree[M << 5]; //序号 int tot = 0; //插入一个数 void insert(int x) { int p = 0; //从高位到低位更新 for (int i = 31; i >= 0; i--) { //取出当前位 int bit = (x >> i) % 2; //没有该节点 新建一个节点 if (!tree[p].son[bit]) { tree[p].son[bit] = ++tot; tree[p].cnt[bit]++; } else tree[p].cnt[bit]++; //往下 p = tree[p].son[bit]; } } //删除一个数 void delet(int x) { int p = 0; for (int i = 31; i >= 0; i--) { //取出当前位 int bit = (x >> i) % 2; tree[p].cnt[bit]--; p = tree[p].son[bit]; } } int query(int x, int l) { int p = 0, ans = 0; for (int i = 31; i >= 0; i--) { int bit1 = (x >> i) % 2; int bit2 = (l >> i) % 2; if (bit2 == 0) {//当bit2 == 1时 只有相等和大于的情况 那就直接相等的情况往后找 int bit = bit1 ^ bit2; p = tree[p].son[bit]; //后面没有节点了 if (p == 0) break; } else {//当bit2等于1是 就只有小于和等于的情况 那就将小雨的情况的cnt加给答案 然后在等于情况继续往下找 int bit = bit1 ^ bit2; if (bit == 0) { ans += tree[p].cnt[1]; p = tree[p].son[bit]; if (p == 0) break; } else { ans += tree[p].cnt[0]; p = tree[p].son[bit]; if (p == 0) break; } } } return ans; } void solve() { cin >> n; while (n--) { cin >> op; if (op == 1) { cin >> x; insert(x); } else if (op == 2) { cin >> x; delet(x); } else { cin >> x >> l; int ans = query(x, l); cout << ans << "\n"; } } } int main() { IOS; int t = 1; //cin >> t; while (t--) { solve(); } }