zoukankan      html  css  js  c++  java
  • 异或子段 [check]

    异或子段



    color{red}{正解部分}

    直接设 F[i,j]F[i, j] 表示前 ii 位分为 jj 段的最大答案不可行, 因为其不满足子结构最优的性质 .

    按位处理, 从高到低 在保证高位尽量取得最大值的前提下检查较低位可不可以取 11,

    现在 checkcheck 当前位填 11 是否合法, 只需将序列分为若干段, 使得每一段 异或 起来 当前答案等于 当前答案 且 段数 Mgeq M 即可认为其合法 .

    分段时从前往后寻找合法子段, 若找到就立马提出, 继续寻找新的子段,

    分到最后可能会剩余一段没有划分完成的子段, 将这个子段放入最后一个确定的子段中,
    为了不影响最后一个确定的子段, 必须满足这个子段的异或和与当前答案的 二进制 位不能重合 .


    color{red}{实现部分}

    #include<bits/stdc++.h>
    #define reg register
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 1005;
    
    int N;
    int M;
    int A[maxn];
    
    bool check(int x){
            int t = 0, s = 0;
            for(reg int i = 1; i <= N; i ++){
                    t ^= A[i];
                    if((t & x) == x) s ++, t = 0;
            }
            if((t & x)) return 0;
            return s >= M;
    }
    
    void Work(){
            N = read(); M = read(); int Ans = 0;
            for(reg int i = 1; i <= N; i ++) A[i] = read();
            for(reg int i = 30; i >= 0; i --)
                    if(check(Ans|(1<<i))) Ans |= (1 << i);
            printf("%d
    ", Ans);
    }
    
    int main(){
            int T = read();
            while(T --) Work();
            return 0;
    }
    
  • 相关阅读:
    Generate Parentheses
    Length of Last Word
    Maximum Subarray
    Count and Say
    二分搜索算法
    Search Insert Position
    Implement strStr()
    Remove Element
    Remove Duplicates from Sorted Array
    Remove Nth Node From End of List
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822410.html
Copyright © 2011-2022 走看看