平衡树
Time Limit: 4000/2000MS (Java/Others)
Memory Limit: 128000/64000KB (Java/Others)
Problem Description
神奇的cxlove有一颗平衡树,其树之神奇无法用语言来描述 OrzOrz。 这棵树支持3种操作: 1、加入一个数到树中,维护平衡树的合法性; 2、给一个数X,用O(1)的时间求出来树中的数Y使得 Y ^ X 最大(异或操作, Pascal 写作 xor , 0 ^ 0 = 0 , 1 ^ 1 = 0 , 0 ^ 1 = 1 , 1 ^ 0 = 1 , 2 ^ 3 = 1) 3、给一个数X,用O(1)的时间求出来树中的数Y使得 Y ^ X 最小(异或操作, Pascal 写作 xor , 0 ^ 0 = 0 , 1 ^ 1 = 0 , 0 ^ 1 = 1 , 1 ^ 0 = 1 , 2 ^ 3 = 1) 请你帮忙实现这颗树。 cxlove由于过于牛,有些事情是无法做到的,你能在1s以内通过就好了。 最后补充一句,cxlove是世界冠军!
Input
第一行是数据组数T (T ≤ 100)。
对于每组数据,第一行是操作数N (N ≤ 10000)。
以下 N 行,每行一个字符串一个数字,分别代表:
- insert X ,加入数 X
- qmax X ,求第2种操作的答案
- qmin X ,求第3种操作的答案
输入保证不存在空树Query的情况 (1 ≤ X ≤ 1e9)
Output
对于操作 2 , 3 输出相应的答案。
Sample Input
1 4 insert 1 insert 2 qmin 1 qmax 1
Sample Output
0 3
Hint
Huge input and output. Please do not use: 1. cin ans cout of C++ 2. scanner of Java(Maybe BufferedReader is quicker)
Source
buaads
将每个数都转化为30位的二进制数(因为2^30-1>1e9)
从左往右,每位上的权值不断减小,所以若要求最大,则前面要尽量不同,求最小则前面要尽量相同,若是不能满足对应加减值
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int N = 30 * 1e4 + 10;
int t,n,x,a[N][2],sz,num[50];
char s[10];
void insert(){
int now = 0;
for(int i=1;i<=30;i++){
if(a[now][num[i]]==-1){
a[now][num[i]] = ++sz;
}
now = a[now][num[i]];
}
}
void query(int p){
int ans = 0,now = 0,base = 1;
for(int i=1;i<30;i++) base<<=1;
for(int i=1;i<=30;i++,base>>=1){
if(p) num[i] = !num[i];
if(a[now][num[i]]==-1){
if(!p) ans += base;
num[i] = !num[i];
}else if(p) ans += base;
now = a[now][num[i]];
}
printf("%d\n",ans);
}
int main()
{
scanf("%d",&t);
while(t--){
memset(a,-1,sizeof a);
sz = 0;
scanf("%d",&n);
while(n--){
scanf("%s%d",s,&x);
for(int i=30;i>0;i--){
num[i] = x&1; x>>=1;
}
if(s[0]=='i') insert();
else if(s[2]=='i') query(0);
else query(1);
}
}
return 0;
}