CodeForces 1208-F Bits And Pieces (SosDp)

Problem:

      传送门

Solution:

      Dp[i] 表示 i 出现的次数,注意我们这里的出现次数不是单纯的 i 出现多少次 , 如果某个数的子集包含 i , 则 i 的出现次数也会增加.
      如果dp[i] >= 2,说明一定存在两个数 按位与 的值是 包含 i 的(包含的意思就是 i 的二进制位 为 1 的位置 其一定也为 1).
      对于update,我们可以直接暴力枚举要放进去的数的所有子集直接更新.考虑到只有 2e6个数,我们每个数只需要大于等于 2 即可(所以可以直接剪枝), 分析可得更新的复杂度最大也为O(2*2e6);

Ac_Code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <stack>
#include <bitset>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#define fir first
#define sec second
using namespace std;

const int maxn = (1<<23);
const int MAXN = 1e6+7;

int n;
int a[MAXN];
int dp[maxn];

void update(int x,int k) {
    if(dp[x] >= 2) return ;
    if(k == -1) return ;
    update(x,k-1);
    if((x&(1<<k))) {
        int d = x-(1<<k);
        update(d,k-1);
        dp[d] ++;
    }
}
    
int main() {
    scanf("%d",&n);
    for(int i=0;i<n;i++) {
        scanf("%d",&a[i]);
    }
    int ans = 0;
    for(int i=n-1;i>=0;i--) {
        if(i<=n-3) {
            int res = (1<<22);
            int cnt = 0;
            for(int j=22;j>=0;j--) { // 这里从贪心的角度,从高位开始,能取就一定取
                if(!(a[i]&res)) {
                    if(dp[(cnt|res)] >= 2) cnt = (res|cnt);
                }
                res >>= 1;
            }
            ans = max(ans,(a[i]|cnt));
        }
        update(a[i],22);
        dp[a[i]]++;
    }
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值