树不要皮,必死无疑;人不要脸,天下无敌|

Tx_Lcy

园龄:2年8个月粉丝:6关注:6

CF1742G Orray

题目传送门

思路

大抵算是一道位运算入门题?

首先为了使 bi 的字典序最大,我们注意到 b1=a1,所以 a1 必然是序列中最大的那个数。

接下来考虑贪心,设当前已经填了 k 个数,此时的或和为 a,则我们从大往小扫,若 maxx 的第 i 位为 0,则接下来我们最好凑出 1 来,因为 2i>j=1i12j,如果实在凑不出来则 skip,如此贪心即可。

代码

#include<bits/stdc++.h>
using namespace std;
int const N=2e5+10;
int a[N],b[N],c[N],n,vis[N],k;
vector<int>q[50];
inline void chk(int &maxx,int id){
    int mxp=0,maxn=maxx;
    for (auto i:q[id]){
        if (vis[i]) continue;
        if ((a[i]|maxx)>maxn) maxn=(a[i]|maxx),mxp=i;
    }
    if (!mxp) return;
    c[++k]=a[mxp];vis[mxp]=1;
    maxx|=a[mxp];
    return;
}
inline void chk(int x){for (int i=30;~i;--i) if (a[x]&(1<<i)) q[i].push_back(x);}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int t;cin>>t;
    while (t--){
        int maxx=0,mxp;cin>>n;
        for (int i=30;~i;--i) q[i].clear();k=0;
        for (int i=1;i<=n;++i) vis[i]=0;
        for (int i=1;i<=n;++i){
            cin>>a[i],chk(i);
            if (a[i]>maxx) maxx=a[i],mxp=i;
        }
        vis[mxp]=1;c[++k]=maxx;
        for (int i=30;~i;--i)
            if (!(maxx&(1<<i)) && q[i].size()) chk(maxx,i);
        for (int i=1;i<=k;++i) cout<<c[i]<<' ';
        for (int i=1;i<=n;++i) if (!vis[i]) cout<<a[i]<<' ';
        cout<<'\n';
    }
    return 0;
}

本文作者:Tx_Lcy

本文链接:https://www.cnblogs.com/tx-lcy/p/16829092.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Tx_Lcy  阅读(47)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起