题意:给定数组ai,要求将ai重新排列满足前缀‘或’数组序列bi字典序最大的性质后输出,定义bi=a0|a1|a2.....|ai.
思路:用变量ans记录目前”前缀或“的大小,首先考虑枚举n次,每次从n个数中找出那个使得ans最大的数据并更新ans.时间复杂度为O()。显然无法通过此题。注意到ai的大小都是在整形之内。这意味着前缀和的最大值为-1,根据或运算性质,易知最多选取32个数字就能够使得前缀或有最大值。故枚举32次为本题正解。时间复杂度为O(32n)。
代码如下:
#include <iostream>
using namespace std;
typedef long long int ll;
ll a[300500];
ll b[300500];
bool vis[300500];
ll n,t,ans,temp,cmp;
int main(){
cin>>t;
while(t--){
cin>>n;
for(ll x=1;x<=n;x++){
cin>>a[x];
vis[x]=0;
b[x]=0;
}
ans=0,temp=0,cmp=0;//ans记录前缀和
for(ll x=1;x<=32;x++){//由于最大只有int,所以最多或运算32次后就一定有或最大
temp=ans;
cmp=0;
for(ll y=1;y<=n;y++){
if((ans|a[y])>temp){
//cout<<y<<endl;
temp=ans|a[y];
cmp=y;
}
}
ans=ans|a[cmp];
b[x]=a[cmp];
vis[cmp]=1;
}
for(ll x=1;x<=32;x++){
if(b[x])//注意别多打了感叹号
cout<<b[x]<<" ";
}
for(ll x=1;x<=n;x++){
if(!vis[x]){
cout<<a[x]<<" ";
}
}
cout<<endl;
}
return 0;
}