求and or xor的最大值

来源:互联网 发布:linux 无故宕机 编辑:程序博客网 时间:2024/06/04 20:00

很有技巧的一道题,题目就是给你一串n个数(n<=105ai<=220)让你分别选两个数,使and or xor最大,这明明就是3道题好不好QAQ

然后我们一个一个看
以下所以“位”指的都是2进制
and:就是从最高的一位向下找,如果这一位为1的数多于两个就取出这些数,然后再取出的这些数里面继续下一位的一样的处理,我就用递归写的
or:这个比较巧妙,也比较暴力,先每个数开一个数组,然后将每个数1的子集全部变为ture,然后去查找每个数,从前向后每一位为0的看有没有可以匹配的,可以就取
xor:我觉得写起来最简单的,读的时候按每一位建一个trie tree,然后查询每一个数就取反然后在里面找,可以就加这一位,不行就不加,一直走20位就可以了

然后代码如下

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<set>#include<queue>#include<algorithm>#include<vector>#include<cstdlib>#include<cmath>#include<ctime>#include<stack>#define INF 2100000000#define ll long long#define clr(x)  memset(x,0,sizeof(x))#define M 100005#define N (1<<20)using namespace std;int a[M];struct tree2{    tree2 *lson,*rson;    int n;}*root,dizhi[M*21];int t;void add(int x){    tree2 *tree=root;    for(int i=20;i>=0;i--)    {        if(x&(1<<i))        {            if(tree->lson==NULL)tree->lson=&dizhi[++t];            tree=tree->lson;        }        else        {            if(tree->rson==NULL)tree->rson=&dizhi[++t];            tree=tree->rson;        }    }}int get_xor(int x){    tree2 *tree=root;    int ans=0;    for(int i=20;i>=0;i--)    {        if(x&(1<<i))        {            if(tree->rson!=NULL)            {                ans+=(1<<i);                tree=tree->rson;            }            else tree=tree->lson;        }        else        {            if(tree->lson!=NULL)            {                ans+=(1<<i);                tree=tree->lson;            }            else tree=tree->rson;        }    }    return ans;}int n,c;int get_and(int *num,int len,int w){    int s[len],sta=0;    clr(s);    int b=0;    for(int i=w;i>=0;i--)    {        for(int j=1;j<=len;j++)        {            if(num[j]&(1<<i))            {                b++;                s[++sta]=num[j];            }        }        if(b>1)        {            int ret=get_and(s,sta,i-1)+(1<<i);            return ret;        }        b=0;sta=0;    }    return 0;}int b[N];int get_or(){    clr(b);    for(int i=1;i<=n;i++)b[a[i]]=1;    for(int i=0;i<=20;i++)        for(int j=0;j<=N;j++)            if(j&(1<<i))b[j^(1<<i)]|=b[j];    int mx=0;    for(int i=1;i<=n;i++)    {        int ans=a[i];        int temp=0;        for(int j=20;j>=0;j--)            if(!(a[i]&(1<<j)))                if(b[temp|(1<<j)])                {                    ans|=(1<<j);                    temp|=(1<<j);                }        mx=max(mx,ans);    }    return mx;}int main(){    freopen("maximum.in","r",stdin);    freopen("maximum.out","w",stdout);    int T;    cin>>T;    while(T--)    {        cin>>n>>c;        if(c==2)root=&dizhi[++t];        clr(a);        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);            if(c==2)add(a[i]);        }        switch (c)        {            case 1:cout<<get_and(a,n,20)<<'\n';break;            case 2:            {                int mx=0;                for(int i=1;i<=n;i++)                    mx=max(mx,get_xor(a[i]));                cout<<mx<<'\n';                break;            }            case 3:cout<<get_or()<<'\n';break;        }    }    return 0;}

大概就是这个样子,如果有什么问题,或错误,请在评论区提出,谢谢。

0 0
原创粉丝点击