秋实大哥有一些菜,每个菜有标号CID,也会来一些客人,每个客人也有标号PID。
对于每个客人, PID^CID (此处为异或)值越大,他越喜欢。
输入:第一行是一个n(1<=n<=100000),表示现在有n道菜。接下来有一个m(1<=m<=100000),表示m个操作
接下来m行,有两种,一, 0 c:表示新研制出来一道标号为c的菜。二,1 p:表示来了一个标号为p的客人,请输出他最喜欢的菜。
字典树来做,用字典树按01分叉,从第20位开始分一直到第0位,然后将这个数保存进来,就是说,从根节点到叶子节点的路径就是这个叶子节点的值的二进制的第20位到第0位。
然后每来一个客人,就查询,查询时同样从最高位开始查,找与PID不同(因为是异或嘛)的支路往下查询,当然如果那个支路下是NULL,表示还没有这样的数,就走走与PID相同的路,然后按这个思想,一直走到第0位那里,对应的值就是他最喜欢的菜的标号。
为什么从最高位往最低位找不同的呢,因为某一位为1,它这一位所代表的值,比后面的所有位全为1代表的值加起来都大啊,找最大,就可以这样贪心地来找。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; #define bit_l 20 //2^17=131072 struct node { int pos; node *ch[2]; node() { pos = 0; ch[0] = ch[1] = NULL; } }; int n, m; node *root; void insert(int x) { //printf("insert "); //printf("cid %d\n", CID[pos]); node *p = root; for (int i = 20; i >= 0; --i) { int f = (x & (1 << i)) != 0; //printf("%d ", f); if (p->ch[f] == NULL) p->ch[f] = new node(); p = p->ch[f]; if (i == 0) p->pos = x; } //printf("\n"); } int query(int t) { //printf("query "); int pos = 0; node *p = root; for (int i = 20; i >= 0; --i) { int f = (t&(1 << i)) != 0; //printf("%d ", f); f = (f == 0) ? 1 : 0; if (p->ch[f] != NULL) p = p->ch[f]; else p = p->ch[f == 1 ? 0 : 1]; if (i == 0) pos = p->pos; } //printf("\n"); return pos; } void destory(node *p) { if (p != NULL) { destory(p->ch[0]); destory(p->ch[1]); delete p; } } int main() { //freopen("input.txt", "r", stdin); scanf("%d", &n); root = new node(); int f, t; for (int i = 1; i <= n; ++i) { scanf("%d", &t); insert(t); } scanf("%d", &m); while (m--) { scanf("%d%d", &f, &t); if (f == 0) { insert(t); } else if (f == 1) printf("%d\n", query(t)); } destory(root); //system("pause"); //while (1); return 0; }