首先暴力做法竟然可以AC。
#include<stdio.h> #include<string.h> #include<ctype.h> #include<math.h> #include<iostream> #include<string> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);} #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;} template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;} const int N=1010,M=0,Z=1e9+7,ms63=1061109567; int casenum,casei; int n; int a[N]; int main() { scanf("%d",&casenum); for(casei=1;casei<=casenum;casei++) { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); int ans=0; for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { for(int k=j+1;k<=n;k++) { gmax(ans,(a[i]+a[j])^a[k]); gmax(ans,(a[i]+a[k])^a[j]); gmax(ans,(a[j]+a[k])^a[i]); } } } printf("%d\n",ans); } return 0; } /* 【trick&&吐槽】 1,字典树是支持删除操作的哦 2,大力出奇迹! 【题意】 T(1000)组数据,最多有10组大数据。 对于每组数据,给你n([3,1000])个数a[],(0<=a[i]<=1e9)。 让你找出三个数a[i],a[j],a[k],i,j,k互不相同 使得(s[i]+s[j])^s[k]的权值尽可能大,并输出这个权值。 【类型】 Trie 【分析】 时限给的9s,我们考虑O(n^3)冲暴力!然后就过掉了! 虽然运算次数高达T*1e9/6,但是位运算很快。这个方法很有启发意义233 */
不过肯定还是字典树做法最好
#include<stdio.h> #include<string.h> #include<ctype.h> #include<math.h> #include<iostream> #include<string> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);} #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;} template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;} const int N=1010,Z=1e9+7,ms63=1061109567; int casenum,casei; int n; int a[N]; int b[32]; int c[N*32][2],num[N*32],id; void ins(int x) { int k=0; for(int i=30;i>=0;i--) { int u=(x>>i)&1; if(c[k][u]==0)c[k][u]=++id; k=c[k][u]; ++num[k]; } } void add(int x,int v) { int k=0; for(int i=30;i>=0;i--) { int u=(x>>i)&1; k=c[k][u]; num[k]+=v; } } int go(int x) { x=~x; int k=0; int tmp=0; for(int i=30;i>=0;i--) { int u=(x>>i)&1; if(num[c[k][u]]) { tmp+=b[i]; k=c[k][u]; } else k=c[k][u^1]; } return tmp; } int main() { for(int i=30;i>=0;i--)b[i]=1<<i; scanf("%d",&casenum); for(casei=1;casei<=casenum;casei++) { memset(c,0,(id+1)*8); memset(num,0,(id+1)*4); id=0; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); int ans=0; for(int i=1;i<=n;i++)ins(a[i]); for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { add(a[i],-1); add(a[j],-1); gmax(ans,go(a[i]+a[j])); add(a[i],1); add(a[j],1); } } printf("%d\n",ans); } return 0; } /* 【trick&&吐槽】 1,大力出奇迹! 2,字典树是支持删除操作的哦 3,字典树的大小是总字符数,不要开小了哦。 【题意】 T(1000)组数据,最多有10组大数据。 对于每组数据,给你n([3,1000])个数a[],(0<=a[i]<=1e9)。 让你找出三个数a[i],a[j],a[k],i,j,k互不相同 使得(s[i]+s[j])^s[k]的权值尽可能大,并输出这个权值。 【类型】 Trie 【分析】 时限给的9s,我们考虑O(n^3)冲暴力!然后就过掉了! 不过暴力能过,很大一部分原因是因为数据水。 我们考虑些复杂度更低的算法。比如很典型的字典树解法。 我们可以考虑枚举pair(i,j),然后再枚举k,并沿着字典树爬升。 然而这个时间复杂度是O(n^3)。 尝试优化,我们很快就发现,其实字典树的总量大概只有O(C[n,2])大小, 我们之所以每次要重新枚举(i,j),是因为这题有要求k!=i且k!=j。 所以有一个想法,我们一开始建立一个容纳这所有n个数的字典树,即把a[]都插入字典树。 然后再枚举所有的pair(i,j),这时把a[i]和a[j]从字典树中删除,即就可避免重复。 然后爬升更新最大值,再恢复a[i]和a[j]。 【时间复杂度】 O(n^2*32) */