大致题意
小T 有个正整数序列,长度为 n, 要你求在这n个数中选择两次;
第一次选出两个不同位置的数,使得这两个数按位取与加按位取或后得到的答案最大;
第二次选择两个不同位置的数,使得这两个数按位取或加按位异或后得到的答案最大。
请求出这两个最大答案。
#include<bits/stdc++.h>
using namespace std;
int nxt[34000005][2];
int cnt;
int n;
long long a[1000005], ans,mxx,mxx2;
void insert(long long a)
{
int u=0;
for(int i =31;~i;--i)
{
if((a>>i)&1)
{
if(!nxt[u][1])
nxt[u][1]=++cnt;
u=nxt[u][1];
}
else
{
if(!nxt[u][0])
nxt[u][0]=++cnt;
u=nxt[u][0];
}
}
}
long long query(long long a)
{
int u=0;
long long num=0;
for(int i =31;~i;--i)
{
if((a>>i)&1)
{
if(nxt[u][0])
{
u=nxt[u][0];
num+=2LL<<i;
}
else
{
u=nxt[u][1];
num+=1LL<<i;
}
}
else
{
if(nxt[u][1])
{
u=nxt[u][1];
num+=2LL<<i;
}
else
u=nxt[u][0];
}
}
return num;
}
signed main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%lld", a + i);
for (int i = 1; i <= n; ++i) {
if(a[i]>mxx)
{
mxx2=mxx;
mxx=a[i];
}
else if(mxx2<a[i])
mxx2=a[i];
}
sort(a + 1, a + 1 + n);
for(int i =1;i<=n;i++)
{
ans=max(ans,query(a[i]));
insert(a[i]);
}
printf("%lld\n%lld", mxx + mxx2, ans);
return 0;
}
以上有排序,n=1e6,ai范围比int范围大100个一,跑了800ms。
#include<bits/stdc++.h>
using namespace std;
int nxt[34000005][2];
int cnt;
int n;
long long a[1000005], ans,mxx,mxx2;
void insert(long long a)
{
int u=0;
for(int i =31;~i;--i)
{
if((a>>i)&1)
{
if(!nxt[u][1])
nxt[u][1]=++cnt;
u=nxt[u][1];
}
else
{
if(!nxt[u][0])
nxt[u][0]=++cnt;
u=nxt[u][0];
}
}
}
long long query(long long a)
{
int u=0;
long long num=0;
for(int i =31;~i;--i)
{
if((a>>i)&1)
{
if(nxt[u][0])
{
u=nxt[u][0];
num+=2LL<<i;
}
else
{
u=nxt[u][1];
num+=1LL<<i;
}
}
else
{
if(nxt[u][1])
{
u=nxt[u][1];
num+=2LL<<i;
}
else
u=nxt[u][0];
}
}
return num;
}
signed main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%lld", a + i);
for (int i = 1; i <= n; ++i) {
if(a[i]>mxx)
{
mxx2=mxx;
mxx=a[i];
}
else if(mxx2<a[i])
mxx2=a[i];
}
// sort(a + 1, a + 1 + n);
for(int i =1;i<=n;i++)
{
ans=max(ans,query(a[i]));
insert(a[i]);
}
printf("%lld\n%lld", mxx + mxx2, ans);
return 0;
}
以上无排序,同样数据跑了1813ms。
求助,感觉时间都是O(nlogn),但是时间实际差了特别多,真的不理解。
本人markdown薄弱,望谅解,不喜勿喷。