题目描述

You are given an array a of n integers.

You need to find the maximum value of ai|(aj&ak) over all triplets (i,j,k) such that i<j<k.

大意

给你一个包含n个整数的序列a

你要在所有满足i<j<k的三元组中找到最大的ai|aj&ak

3<=n<=106

0<=a[i]<=2*106

题解

一,位运算

|指的是二进制后的按位或

如  2|5=7,7|9=15

&指的是二进制后的按位且

如  3&2=2,13&10=8

二、题目

说完了简单的位运算,我们正式进入主题

“按位或”有个特点,就是如果一个数当前位置上是1,则结果当前位置上也一定是1

看上去好废话啊

这样的话,我们就可以枚举更方便确定的a[i]

我们不妨定义a[j]&a[k]的值叫q

那么q一定是a[j]和a[k]的子集(数字的子集是转化为二进制后,每一位都小于等于原数字的数,而不是集合)

因此,我们就可以遍历这些数字的子集,要用dfs执行

当然,别忘了高位优先 !

三、dfs深搜

这部分的深搜很像状压DP,我们只需要找出现了两次的子集即可,同时我们还要避免同一个数的子集算了两次

如110的子集010和100的下一个子集都是000

用vis数组记录即可

四、代码

#include<iostream>
using namespace std;
int sum[2000010],a[1000010],vis[2000010],n,ans;
void h(int x,int y){
if(sum[x]>1||vis[x]==y) return ;
++sum[x];
vis[x]=y;
for(int i=0;(1<<i-1)<x;i++)
if(x&(1<<i)) h(x^(1<<i),y);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
h(a[n],n);
h(a[n-1],n-1);
for(int i=n-2;i>=1;i--){
int k=0;
for(int j=20;j>=0;j--){
if(!(a[i]&(1<<j))&&sum[k^(1<<j)]>1) k^=(1<<j);
}
ans=max(ans,a[i]|k);
h(a[i],i);
}
printf("%d",ans);
return 0;
}

最新文章

  1. Java-计划存储
  2. PhotoShop常用快捷键
  3. mybatis动态SQL - like
  4. 更新包地址安装新版node.js
  5. shell 判断字符串是否为数字
  6. 微信小程序之----audio音频播放
  7. python实战第一天-环境的安装
  8. C# 控件的缩写
  9. Angular4.x通过路由守卫进行路由重定向,实现根据条件跳转到相应的页面
  10. 指针超强汇总(谨记优先级:() &gt; [] &gt; *)
  11. Windows下SVN服务器搭建和基本操作(服务端、客户端)
  12. .NET方法无限传参数技术
  13. linux把文件压缩成.tar.gz的命令
  14. Python编程基础[条件语句if 循环语句 for,while](二)
  15. Kafka命令操作
  16. tst
  17. (转)python3之模块io使用流的核心工具
  18. SharePoint Online 创建文档库
  19. Zookeeper系统设计的优点
  20. java 自定义泛型

热门文章

  1. C#泛型接口请求封装类
  2. c# 使用 Redis
  3. 魔兽世界2009年更换代理,九城CEO至全体员工公开信
  4. 微信小程序与微信公众号之间支付问题解决方案
  5. SAP BW/4HANA 听课笔记
  6. git基础代码获取
  7. redis底层数据结构之压缩列表(ziplist)
  8. MobaXterm激活专业版
  9. Java并发编程 —— synchronized关键字
  10. Visualization: Pie Chart(可视化:饼图)