hihocoder 1496:寻找最大值(高维前缀最大次大值)

Posted forever97‘s blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hihocoder 1496:寻找最大值(高维前缀最大次大值)相关的知识,希望对你有一定的参考价值。

 

【题目链接】 https://hihocoder.com/problemset/problem/1496

 

【题目大意】

  给定N个数A1, A2, A3, ... AN,
  从中找到两个数Ai和Aj(i≠j)使得乘积Ai*Aj*(Ai&Aj)最大

 

【题解】

  我们可以枚举x&y的结果z,找出两个数x&y==z使得x*y最大,更新答案即可,
  条件可以被削弱为z为x&y的子集,这种条件放缩不会导致最优解的丢失,
  z为x&y的子集等价于z为x的子集并且z为y的子集。
  那么我们只要找出以z为子集的最大值和次大值,然后枚举z即可计算出答案。
  复杂度O(k*2^k).

 

【代码】

#include <cstdio>
#include <algorithm>
using namespace std;
struct data{
    int val[2];
    data operator +(const data &rhs)const{
        int t_val[2]={val[0],val[1]};
        for(int i=0;i<2;i++){
            if(rhs.val[i]>t_val[0]){
                t_val[1]=t_val[0];
                t_val[0]=rhs.val[i];
            }else if(rhs.val[i]>t_val[1])t_val[1]=rhs.val[i];
        }return data{t_val[0],t_val[1]};
    }
}dp[(1<<20)+10];
int T,n;
int main(){
    scanf("%d",&T);
    int all=1<<20;
    while(T--){
        for(int i=0;i<all;i++)dp[i]=data{0,0};
        scanf("%d",&n);
        for(int i=1,x;i<=n;i++){
            scanf("%d",&x);
            dp[x]=dp[x]+data{x,0};
        } 
        for(int i=0;i<20;i++)
            for(int j=0;j<all;j++)
                if(~j&(1<<i))dp[j]=dp[j]+dp[j|(1<<i)];
        long long ans=0;
        for(int i=0;i<all;i++)ans=max(ans,1LL*i*dp[i].val[0]*dp[i].val[1]);
        printf("%lld\n",ans);
    }return 0;
}

以上是关于hihocoder 1496:寻找最大值(高维前缀最大次大值)的主要内容,如果未能解决你的问题,请参考以下文章

hihocoder1496(高维前缀和)

hihocoder1860 最大异或和

hihocoder1800

hihoCoder 第254周 hiho一下 寻找最大值

hihocoder offer收割编程练习赛12 D 寻找最大值

hihocoder-1274 自行车架(高维dp)