您的位置:首页 > 其它

【HDU5536 2015长春赛区 J】【字典树or暴力】Chip Factory 字典序做法+暴力做法

2015-11-03 13:59 495 查看
首先暴力做法竟然可以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
;
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
;
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)

*/

此外这题还能二分做哦,可以自己思考。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM ICPC 算法 HDU 脑洞