CDOJ 1060 秋实大哥与快餐店 字典树

来源:互联网 发布:alias软件销售招聘 编辑:程序博客网 时间:2024/05/16 09:14

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

0 0