Maximum

· · 题解

Maximum最大值 TJ

这垃圾题目,放在字典树题单里面却用一堆乱七八糟的东西。。。

题目大意

给你N个数,一种位运算,任选两数计算,求出能得到的最大值

思路

三个位运算,我们分类讨论做一波:

得出算法后,我们就开始写代码:

核心代码:

注:inline和快读是我平时卡常用的优化时间的,但你也可以不写只是没我快而已

另外,我的数字是用now数组存的,老是写混。。。

然后即可得到正解:(注释就不写了)
#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while('0'>ch||'9'<ch){if(ch=='-') f=-f;ch=getchar();}
    while('0'<=ch&&'9'>=ch){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*f;
}
inline int Max(int x,int y){
    return x>y?x:y;
}
int trie[1600001][2],cnt;
int now[100001];
inline void insert(int n){
    int p=0;
    for(int i=20;i>=0;i--){
        int op=(n>>i)&1;
        if(!trie[p][op]) trie[p][op]=++cnt;
        p=trie[p][op];
    }
}
inline int searchxor(int n){
    int p=0,num=0;
    for(int i=20;i>=0;i--){
        int op=(n>>i)&1;
        if(trie[p][op^1]) p=trie[p][op^1],num=num<<1|1;
        else p=trie[p][op],num<<=1;
    }
    return num;
}
bool vis[100001];
inline int searchand(int n){
    memset(vis,0,sizeof vis);
    for(int i=20;i>=0;i--){
        int cnt=0;
        for(int j=1;j<=n;j++) if(!vis[j]) cnt+=(now[j]>>i)&1;
        if(cnt==2){
            int f=-1;
            for(int j=1;j<=n;j++)
                if(!vis[j]&&((now[j]>>i)&1)&&f==-1) f=now[j];
                else if(!vis[j]&&((now[j]>>i)&1)&&f!=-1) return f&now[j];
        }
        else if(cnt>2)
            for(int j=1;j<=n;j++) if(!((now[j]>>i)&1)) vis[j]=1;
    }
    int f=-1;
    for(int i=1;i<=n;i++)
        if(!vis[i]&&f==-1) f=now[i];
        else if(!vis[i]&&f!=-1) return f&now[i];
    return 1;
}
bool f[10000001];
inline void init(int n){
    for(int i=1;i<=n;i++)
        for(int j=now[i];j;j=(j-1)&now[i]) f[j]=1;
}
inline int searchor(int n){
    memset(f,0,sizeof f);
    init(n);
    int ans=0;
    for(int i=1;i<=n;i++){
        int t=0;
        for(int j=20;j>=0;j--){
            if((now[i]>>j)&1) continue;
            else if(f[t|(1<<j)]) t|=(1<<j);
        }
        ans=Max(ans,now[i]|t);
    }
    return ans;
}
int main(){
    int T=read();
    while(T--){
        memset(trie,0,sizeof trie);
        int n=read(),c=read(),ans=0;
        for(int i=1;i<=n;i++){
            now[i]=read();
            insert(now[i]);
        }
        if(c==1) ans=searchand(n);
        else if(c==2) for(int i=1;i<=n;i++) ans=max(ans,searchxor(now[i]));
        else ans=searchor(n);
        printf("%d\n",ans);
    }
    return 0;
}

这万恶的绝世好题终于完了!!!