zoukankan      html  css  js  c++  java
  • 搜索题

    搜索题

    题目描述

     

    小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;
    }
  • 相关阅读:
    Linux _条件变量
    Linux _pthread 线程的同步 浅见
    Linux pthread 线程 浅解
    Linux _守护进程 浅解
    Linux _孤儿进程和僵尸进程 浅见
    Linux 小技巧
    Linux _sem 信号量 V_P
    树莓派ZeroW上传数据文件到阿里云对象存储OSS(Python)
    树莓派ZeroW开机自动运行
    树莓派ZeroW串口通讯
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358789.html
Copyright © 2011-2022 走看看