qscqesze
Published on 2017-09-02 11:31 in 暂未分类 with qscqesze

# Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2) F. Bits And Pieces sosdp

## 题面

You are given an array 𝑎 of 𝑛 integers.

You need to find the maximum value of 𝑎𝑖|(𝑎𝑗&𝑎𝑘) over all triplets (𝑖,𝑗,𝑘) such that 𝑖<𝑗<𝑘.

Here & denotes the bitwise AND operation, and | denotes the bitwise OR operation.

## Input

The first line of input contains the integer 𝑛 (3≤𝑛≤106), the size of the array 𝑎.

Next line contains 𝑛 space separated integers 𝑎1, 𝑎2, ..., 𝑎𝑛 (0≤𝑎𝑖≤2⋅106), representing the elements of the array 𝑎.

## Output

Output a single integer, the maximum value of the expression given in the statement.

3
2 4 6

6

4
2 8 4 7

12

## Note

In the first example, the only possible triplet is (1,2,3). Hence, the answer is 2|(4&6)=6.

In the second example, there are 4 possible triplets:

(1,2,3), value of which is 2|(8&4)=2.
(1,2,4), value of which is 2|(8&7)=2.
(1,3,4), value of which is 2|(4&7)=6.
(2,3,4), value of which is 8|(4&7)=12.
The maximum value hence is 12.

## 题解

(a[j]&a[k])这个东西我们单独维护，枚举a[j]的每一位，举个例子比如a[j]是10001，那么我们让cnt[10000],cnt[10001],cnt[00001]都加1；比如00101，我们让cnt[00100]和cnt[00001],cnt[00101]都加上1。

## 代码

#include<bits/stdc++.h>
using namespace std;
const int N=4000005;
int n,cnt[N],ans,a[N];
void insert(int x,int y){
if (cnt[x|y]==2)return;
if (x==0){
cnt[y]++;
return;
}
insert(x&x-1,y|x&-x);
insert(x&x-1,y);
// x&x-1是取消最小的一位，x&-x是取最小的一位
}
int main() {
scanf("%d",&n);
for (int i=1;i<=n;i++)scanf("%d",&a[i]);
for (int i=n;i>=1;i--){
if (i+2<=n){
int now=0;
for (int j=20;j>=0;j--)
if (!((1<<j)&a[i])&&cnt[now|1<<j]==2)now|=1<<j;
ans=max(ans,now|a[i]);
}
insert(a[i],0);
}
printf("%d\n",ans);
return 0;
}

/* sos dp
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1<<21;
int dp[maxn][21],a[maxn],n;
void sosdp(int num,int k){
if(k>20)return;
if(dp[num][k]>1)return;
dp[num][k]++;
sosdp(num,k+1);
if(num>>k&1){
sosdp(num^(1<<k),k);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int ans = 0;
for(int i=n;i>=1;i--){
int res = 0, t = 0;
for(int j=20;j>=0;j--){
if(a[i]>>j&1){
res|=1<<j;
}else if(dp[t|(1<<j)][20]>1){
res|=1<<j;
t|=1<<j;
}
}
sosdp(a[i],0);
if(i<=n-2){
ans=max(ans,res);
}
}
cout<<ans<<endl;
}
*/
posted @ 2019-09-03 14:56  qscqesze  阅读(184)  评论(0编辑  收藏