F. Ivan and Burgers 前缀线性基

这篇博客探讨了一种处理数组异或查询的方法,即建立前缀线性基,并详细解释了如何在给定区间[l, r]内求最大异或值。在面对重复数值可能导致的冲突时,提出了采用贪心策略,优先保留原序列中较大数值的策略,以优化区间查询效率。" 109994247,9915217,死磕字节跳动:11轮面试经验与复习宝典,"['面试经验', 'Java', '数据库', '分布式系统', '面试准备']
摘要由CSDN通过智能技术生成

传送门

题意:首先输入n,代表当前有n个数,然后再输入m,代表m次询问,每一次询问是询问区间[l,r],这段区间内的数的最大异或值。

思路:处理出来一个前缀线性基,记录线性基上该位置是在原序列的哪个位置,求值的时候在第r个线性基上找,如果位置>=l则是合法的。如果有两个相同的数在同一位,遇到这种情况则用贪心的想法,如果在同一位上明显原序列越大的数越优,因为如果把原序列小的留下,则区间长度较小时明显没有原序列大的数更优,所以贪心的留下原序列大的。和这题很像

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int maxn=5e5+10;
    int per[maxn][30];
    int pos[maxn][30];
    int insert(int k,int w)
    {
        for(int i=0;i<=25;i++)
        {
            per[k][i]=per[k-1][i];
            pos[k][i]=pos[k-1][i];
        }
        int ans=k;
        for(int i=25;i>=0;i--)
        {
            if(w&(1<<i))
            {
                if(!per[k][i])
                {
                    per[k][i]=w;
                    pos[k][i]=ans;
                    break;
                }
                else{
                    if(ans>pos[k][i])
                    {
                        swap(ans,pos[k][i]);
                        swap(w,per[k][i]);
                    }
                    w^=per[k][i];
                }
            }
        }
        return w>0;// 等于0表示能表示
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int w;
            scanf("%d",&w);
            insert(i,w);
        }
        int m;
        scanf("%d",&m);
        while(m--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            int ans=0;
            for(int i=25;i>=0;i--)
            {
                if(per[r][i]>0&&pos[r][i]>=l)//
                {
                    ans=max(ans,ans^per[r][i]);
                }
            }
            printf("%d\n",ans);
            //cout<<ans<<endl;
        }
        return 0;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值