zoukankan      html  css  js  c++  java
  • 第K大子集-LH

    题解:搜索+二分

    对于每个数有选与不选两种情况。然后我们先搜前一半的状态,每个数选还是不选。

    有2^17种,然后我将每种状态拍一个序先存着。然后我再搜后一半的状态,2^18种。

    假设后一半某一种情况的子集和为w,我们二分的答案为t,那么我们在前一半二分找t-w。

    就是前一半和后一半拼成了一个子集。如果子集全在后一半怎么办?因为前一半有个空集,

    空集和后一半拼子集还是只在后一半的。

    代码:没有评测的地方 我(*゜ロ゜)ノ瞎写的

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 200000
    #define LL long long
    using namespace std;
    
    int n,an,k,bn,p,q,a[maxn];
    LL l,r,mid,ans,g[maxn],f[maxn];
    
    bool check(LL t){
        int all=0;
        for(int i=1;i<=q;i++){
            LL w=t-f[i];
            int c=lower_bound(g+1,g+p+1,w)-g;
            all+=p-c+1;
        }
        return all>=k;
    }
    
    int main(){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),r+=a[i];
        an=n/2;bn=n-an;
        for(int st=0;st<(1<<an);st++){
            LL all=0;
            for(int i=0;i<an;i++)
             if((st>>i)&1)all+=a[i+1];
            g[++p]=all;
        }
        for(int st=0;st<(1<<bn);st++){
            LL all=0;
            for(int i=0;i<bn;i++)
             if((st>>i)&1)all+=a[n-i];
            f[++q]=all;
        }
        sort(g+1,g+p+1);sort(f+1,f+q+1);
        while(l<=r){
            mid=(l+r)>>1;
            if(check(mid)){
                ans=mid;l=mid+1;
            }else r=mid-1;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    生产环境Crontab专业实例
    Linux系统定时任务介绍
    Linux文件属性改变命令chown-chgrp-chattr-lsattr实践
    Linux命令总结
    Linux特殊权限位suid、sgid深度详细及实践
    企业场景-网站目录安全权限深度讲解及umask知识
    shell简介
    Nginx模块及配置虚拟主机
    安装Nginx
    Nginx简介
  • 原文地址:https://www.cnblogs.com/zzyh/p/7642651.html
Copyright © 2011-2022 走看看