题目描述
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;
}
不懂代码一定要手动模拟一下哦~