• 搜索题


    搜索题

    题目描述

     

    小H是一个热爱出毒瘤题的女孩子。

    小H按照老师要求出了一道搜索题。这是一道只有题目和搜索有关的题目。

    现在你有一个长度为n的数列A,每个数为ai,你要将它分成m段,每段至少1个数。令每段的异或值为ci。

    你需要最小化所有ci或起来的值。

     

    【数据范围】 1≤m≤n≤5*10^5,0≤ai≤10^18

    solution

    考虑从高位开始贪心

    如果这一位出现了奇数个一,那么这一位就应该是不合法的,可以跳过

    如果是偶数个,那么我们可以贪心判断。

    那么怎么在保证之前合法的时候寻找当下合法的的方案呢

    我开了个变量M 表示第i位是否能做到合法,如果能就为1

    如果当前所有为的异或和为t,且t&m==0 则当前位为一个合法的划分

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define ll long long
    #define maxn 500005
    using namespace std;
    int n,m,tot;
    ll a[maxn],flag,Max,ans,M;
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            Max=max(Max,a[i]);
        }
        int bs;
        for(bs=0;(ll)(1LL<<bs)<=Max;bs++);M=0;
        for(int ws=bs;ws>=0;ws--){
            int num=0;
            for(int i=1;i<=n;i++)
            if(a[i]&((ll)(1LL<<ws)))num++;
            if(num%2==0){
                M+=(ll)(1LL<<ws);
                int cnt=0;ll t=0;
                for(int i=1;i<=n;i++){
                    t=t^a[i];
                    if((t&M)==0)cnt++,t=0;
                    if(cnt==m)break;
                }
                if(cnt!=m)ans+=(ll)(1LL<<ws),M-=(ll)(1LL<<ws),tot--;
            }
            else ans+=(ll)(1LL<<ws);
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    实战:垂直电商如何撬动“女人腰包”
    谈谈项目收尾
    项目管理心得:一个项目经理的个人体会、经验总结
    IT项目经理沟通技巧的重要性
    项目跟踪:项目跟踪要跟踪什么呢?
    会员营销,你真的做到了吗?
    Git入门——基础知识问答
    文摘:威胁建模(STRIDE方法)
    写在2015年工作的第一天
    简化工作——我的bat文件
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358789.html
Copyright © 2020-2023  润新知