题意:给你n个数,从中选出三个数a,b,c,然后(a+b)^c,这个式子的值是最大的。
思路:如果来三个for循环,果断TLE,所以想到了字典树,就是先把所有的数字都插进去,在查询的时候就先把确定了的那两个数字删掉,然后在字典树中求出异或的最大值,得到结果后,再把两个数字插回去。
P.S.一开始我的数组开到了45*10^5+10,然后他给我TLE,然后当我把数组开到10^5+10的时候,A了···········,居然是数组爆我时间了,我勒个擦。
#include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<queue> #include<map> #include<stack> #include<set> #define ll long long #define maxn 100010 #define PI acos(-1.0) //圆周率 const ll INF = 1e18; const int len=31; using namespace std; struct node { int sz; int ch[maxn][2]; int sum[maxn]; void trie() { sz=1; memset(ch,0,sizeof(ch)); memset(sum,0,sizeof(sum)); } void add(int x) { int u=0; bool f; for(int i=len;i>=0;i--) { f=x&(1<<i); if(ch[u][f]==0) ch[u][f]=sz++; u=ch[u][f]; sum[u]++; } } void del(int x) { int u=0; bool f; for(int i=len;i>=0;i--) { f=x&(1<<i); u=ch[u][f]; sum[u]--; } } int query(int x) { int u=0; bool f; int cnt=0; for(int i=len;i>=0;i--) { f=x&(1<<i); if(sum[ch[u][!f]]) f=!f; u=ch[u][f]; cnt=cnt|(f<<i); } return cnt; } }st; int T,n; int num[1100]; int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); st.trie(); int k=0; for(int i=0;i<n;i++) { scanf("%d",&num[i]); st.add(num[i]); } ll ans=0; ll big=0; for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { st.del(num[i]); st.del(num[j]); int nut=st.query(num[i]+num[j]); big=nut^(num[i]+num[j]); ans=ans>big?ans:big; st.add(num[i]); st.add(num[j]); } } printf("%d ",ans); } return 0; }