鏈接:https://ac.nowcoder.com/acm/contest/549/D
來源:牛客網
題目描述
位運算是一個非常重要的東西。而小A最近在學習位運算,小A看到了一道很簡單的例題,是說從N個數裏面選出N-1個數要讓它們或起來的值最大,小A想知道這個答案是多少。你可以幫幫他嗎?
輸入描述:
第一行一個整數N表示有N個數接下來一行N個數表示A1,A2…AN
輸出描述:
一行輸出個結果代表最大值
輸入
5
1 2 4 8 16
輸出
30
說明
選擇2,4,8,16或的和是最大的,沒有比這個更大的方案。
備註: 1 ≤ N ≤ 5e6,1 ≤ A[i] ≤ longlong
分析:
雖說是位運算,但是這題和二進制沒啥關係…
要去除N個數中的一個,使剩下的N-1個數最大,或運算的話要除去的數並沒有什麼特徵,於是要枚舉被除去的數。
O(N2)的枚舉肯定是不行的,這裏就要用到技巧了,先預處理 前 i 個數的或和,後 i 個數的或和,分別放入 L[i] 和 R[i] 中,然後枚舉被除去的數,則有
該方法可適用於定義一種運算,然後求去除其中一個數然後運算後的最大/最小值。
以下代碼:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=5e6+10;
LL A[maxn],L[maxn],R[maxn]; //外部定義,數組全部置零
int main()
{
int N;
LL ans=0;
scanf("%d",&N);
for(int i=1;i<=N;i++)
scanf("%lld",&A[i]);
for(int i=1;i<=N;i++) //注意L R的初值都是0
L[i]=L[i-1]|A[i]; //這樣保證 起始數 與 0 或後是其本身
for(int i=N;i>=1;i--)
R[i]=R[i+1]|A[i];
for(int i=1;i<=N;i++)
ans=max(ans,L[i-1]|R[i+1]);
printf("%lld",ans);
return 0;
}