https://acm.hdu.edu.cn/submit.php?pid=6955
题意:给你n个数,输入一个数s,问n个数哪个与s异或最大。
被TLE傻了,最后数组开大了一倍过了,不知道为什么数组开小不是RE。
改了一个多小时,人傻了。
思路:01字典树经典用法,用所有n个数的二进制建一颗字典树,再来对比给出的s的二进制。
时间复杂度
O
(
n
l
g
n
)
O(nlgn)
O(nlgn)。
在重建树的过程种边初始化边建树可以减少时间复杂度,但减少的只是常数,直接清空也可以过这道题。
#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define rep(i, x, y) for(auto i=(x);i<=(y);++i)
#define dep(i, x, y) for(auto i=(x);i>=(y);--i)
#define gcd(a, b) __gcd(a,b)
const long long mod = 1e9 + 7;
const int maxn = 100000 + 5;
int lowbit(int x) { return x & -x; }
bool ispow(int n) { return (n & (n - 1)) == 0; }//O(1) 判断是否是 2^k(2的k次方)
int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int trie[32*maxn][2];
int a[32*maxn];
signed main(){
int t;
cin>>t;
int q=1;
while(t--){
int n,k;
scanf("%d%d",&n,&k);
int sum=0;
rep(i,1,n){
scanf("%d",&a[i]);
// a[i]^=a[-1];
}
trie[1][0]=trie[1][1]=0;
int cnt = 1;
rep(i, 1, n) {
int p=1;
dep(j,31,0){
int w = (a[i] >> j) & 1;
if(!trie[p][w]){
trie[p][w] = ++cnt;
trie[cnt][1] = trie[cnt][0] = 0;
}
p=trie[p][w];
}
}
printf("Case #%d:\n",q);
while(k--){
int s;
scanf("%d",&s);
int p=1;
int ans=0;
dep(i,31,0){
int z=(s>>i)&1;
if(trie[p][z^1]){
p=trie[p][z^1];
ans+=((z^1)<<i);
}else {
p=trie[p][z];
ans+=(z<<i);
}
}
printf("%d\n",ans);
}
q++;
}
return 0;
}