秋实大哥有一些菜,每个菜有标号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;
}