秋实大哥与快餐店
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
朝为田舍郎,暮登天子堂。秋实大哥从小就怀抱有远大的理想,所以他开了一家快餐店。
秋实大哥根据菜的口感,给每一道菜一个唯一的 CID CID,同时对于前来的客人,根据他们的口味喜好,秋实大哥会给每一个客人一个 PID PID。
对于一个标号为 PID PID的客人,他对标号为 CID CID的菜的喜爱程度为 PID∧CID PID∧CID( ∧ ∧表示按位异或),该值越大表示越喜欢。
秋实大哥实在太忙了,现在他需要你来帮忙照看一下他的店铺。
Input
第一行包含一个整数 n n,表示秋实大哥的餐馆内现在有 n n道菜。
接下来一行包含 n n个整数,分别表示每一道菜的 CID CID。
接下来一行包含一个整数 m m,表示接下来发生了 m m件事。
接下来的 m m行,每一行为以下两种事件之一:
0 c : 表示秋实大哥最新研制出一道标号为c的菜 1 p : 表示来了一位标号为p的客人,请你在已有的菜中找出一道他最喜爱的菜
1≤n,m≤100000 1≤n,m≤100000, 0≤PID,CID≤1000000 0≤PID,CID≤1000000。
Output
对于每一个 1 1 p p事件输出一个整数,表示该客人最喜欢的菜的标号。
Sample Input | Sample Output |
---|---|
1 1 3 1 1 0 2 1 1 | 1 2 |
这道题如果按照普通的查询是O(m*n),会超时,所以需要想想其他办法来解决,这里我们注意到是异或操作,所以我们可以先转化为2进制来处理,只要能得到最大的异或值就可以了,所以我们这里使用了字典树进行处理,主要是要想到怎么转化,没想到就很难进行处理了。
ac代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
/*
log2 1e6 向上取整为20,即树的高度小于等于21,使用满二叉树来进行存储,2^22
*/
const int maxbit = 20;
struct data
{
char l,r;
int id;//存储id值
};
data tree[(1<<22) + 50],n;
void insert(int x)
{
int ptr = 1,cur = 0;
while(cur < maxbit)
{
if (x >> (maxbit-cur-1) & 1)
{
tree[ptr].r = 1;
ptr = ptr*2+1;
}
else
{
tree[ptr].l = 1;
ptr <<= 1;
}
cur++;
}
ptr <<= 1;
tree[ptr].id = x;
}
int find(int x)
{
int ptr = 1 , cur = 0 , tar = ~x;
while(cur < maxbit)
{
if ( (tar >> (maxbit-cur-1) ) & 1)
{
if (tree[ptr].r)
ptr = ptr*2+1;
else
ptr <<= 1; //左子树
}
else
{
if (tree[ptr].l)
ptr <<= 1;
else
ptr = ptr*2+1;//右子树
}
cur++;
}
ptr <<= 1;
return tree[ptr].id;
}
int main()
{
int n,m,a,b;
memset(tree,0,sizeof(tree));//先把所有值置0
scanf("%d",&n);
for(int i = 0 ; i < n ; ++ i)
{
int temp;
scanf("%d",&temp);
insert(temp);//读一个数插入一个数
}
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&a,&b);
if (a & 1)
printf("%d\n",find(b));
else
insert(b);
}
return 0;
}
题目网址: 点击打开链接http://acm.uestc.edu.cn/#/problem/show/1060