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;
    }
  • 相关阅读:
    C语言中可变函数参数变量的实现
    Oracle电话面试
    JS和C#方法相互调用
    asp.net 页面从初始化到卸载事件顺序
    解决.NET CF 3.5 Bitmap(Stream)未处理异常问题
    sql2008新增时间类数据类型学习
    c#和Javascript操作同一json对象
    被研究生了
    分形
    跑钱
  • 原文地址:https://www.cnblogs.com/zzyh/p/7642651.html
Copyright © 2011-2022 走看看