• 第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;
    }
  • 相关阅读:
    Hibernate 总结
    Mybatis 总结
    Mybatis原生DataSource源码解析
    Spring Cloud 服务安全
    Mybatis原生源码解析
    最好的Http客户端--Feign 源码分析
    Zuul整合Hystrix断路器
    Zuul核心-预定义Filter
    Feign性能优化
    Feign整合Ribbon负载均衡
  • 原文地址:https://www.cnblogs.com/zzyh/p/7642651.html
Copyright © 2020-2023  润新知