小苯的数组切分 ---- 牛客月赛

文章讨论了如何通过最优方式将一个数组划分为三段,每段分别进行异或、或和与运算,然后求和得到小苯的最大得分。解题关键在于理解按位运算的特性并转化为前缀和和后缀和问题。
摘要由CSDN通过智能技术生成

题目描述

qionghuaqionghuaqionghua 给了小苯一个长度为 n 的数组 a,希望小苯将数组 aaa 分为恰好非空的三段。即:[1,l−1],[l,r],[r+1,n]这三段,其中 1< l≤r<n。接着:

∙  第一段的所有数字做  ⊕(按位异或)运算。
∙  第二段的所有数字做  |(按位)运算。

∙  第三段的所有数字做  &(按位)运算。

将这三段数字运算的结果做加法求和,作为小苯的得分。
小苯想知道他如果以最优的方案切分数组,最多能获得多少得分,请你帮他算一算吧。

输入描述:

输入包含两行。
第一行一个正整数 n(3≤n≤2×105),表示数组 a 的长度。
第二行 n 个正整数 ai(1≤ai≤109),表示数组 a 的元素。

输出描述:

输出包含一行一个正整数,表示小苯的最高得分。

示例1

输入

4
3 4 2 2

输出

11

示例2

输入

4
2 3 3 3

输出

8


 解析:

这个题首先,要了解^ , | , &这三个符号的符号特性 ,(^)异或的特性即可能不变,有可能变大,又可能变小。(|)或的特性:越或越大,(&)与的特性:越与越小。所以根据符号特性,我们可以确定与这个区间段肯定是一个数,因为与其与上一个数,不如把这个数给前面岂不是更好所以我们就可以把剩下的数分为两个 区间段,然后我们就可以发现这好像是一个前缀和的问题,但是并不是我们传统的前缀和,注意区间的区分和前缀和后缀,即可拿捏这个题!


AC代码如下:

#include<iostream>

using namespace std;

const int N = 2e5+10;
long long a[N],yh[N],huo[N];

int main()
{
    long long n,ans = 0;
    cin >> n;
    for(int i=1;i<=n;i++) cin >> a[i];
    //注意要留出等于0这种情况哦
    yh[1] = a[1];//前缀和第一个数(异或)
    huo[n-2] = a[n-1];//(或)后缀和第一个数
    for(int i=2;i<n-1;i++)
    {
        yh[i] = yh[i-1] ^ a[i];
    }
    for(int i=n-2;i>=1;i--)
    {
        huo[i] = huo[i+1] | a[i+1];
    }
    //找出相加最大的情况
    for(int i=1;i<n;i++)
    {
        ans = max(ans,yh[i]+huo[i]);
    }
    cout << ans + a[n] << endl;
} 

不懂代码一定要手动模拟一下哦~ 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值