zoukankan      html  css  js  c++  java
  • 北京集训TEST13——PA(第k小数)

    题目:

    Description

    【问题描述】

        从n个数中选若干(至少1)个数求和,求所有方案中第k小的和(和相同但取法不同的视为不同方案)。
    【输入格式】
        第一行输入2个正整数n,k。
        第二行输入这n个正整数。
    【输出格式】
        输出第k小的和。
    【样例输入】
    5 12
    1 2 3 5 8
    【样例输出】
    8
    【样例解释】
        前12小的和分别为:1 2 3 3 4 5 5 6 6 7 8 8
    【数据规模和约定】
        测试点1,n<=16。
        测试点2-3,n<=100,k<=500。
        测试点4-5,n<=1000,k<=5000。
        测试点6-8,n<=10^5,k<=5*10^5。
        测试点9-10,n<=35。
        对于所有数据,1<=k<2^n,n个正整数每个都不超过10^9。


    题解:

      80%数据:用二元组(sum,i)表示和为sum,当前考虑第i个位置是否要选,以sum+a[i]为权值维护。
    每次扩展到(sum+a[i],i)和(sum,i+1)。
    时间复杂度O(KlogK)
    剩下20%数据:二分答案以后折半搜索,时间复杂度O(2^{K/2}logW)

    心得:

      优先队列是个好东西,折半搜索是个好东西;

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<queue>
    using namespace std;
    const int N=100005;
    const int M=1e7+5;
    struct node
    {
      long long sum;
      int pos;
      node(long long sum,int pos):sum(sum),pos(pos){}
    };
    inline bool operator < (const node &a,const node &b)
    {
      return a.sum>b.sum;
    }
    priority_queue<node>que;
    long long num[N];
    long long vala[M],valb[M];
    long long k;
    int tota=0,totb=0;
    int n;
    void solve1()
    {
      que.push(node(num[1],2));
      for(int i=1;i<k;i++)
      {
        long long tsum=que.top().sum;
        int tpos=que.top().pos;
        que.pop();  
        if(tpos<=n)
        { 
          que.push(node(tsum-num[tpos-1]+num[tpos],tpos+1));
          que.push(node(tsum+num[tpos],tpos+1));
        }
      }
      printf("%lld
    ",que.top().sum);
    }
    void dfs1(int u,int des,long long val)
    {
      if(u>des)
      {  
        if(val) 
          vala[++tota]=val;
      }
      else
      {  
        dfs1(u+1,des,val+num[u]);
        dfs1(u+1,des,val);
      }
    }
    void dfs2(int u,int des,long long val)
    {
      if(u>des)
        if(val) 
          valb[++totb]=val;
      else
      {  
        dfs2(u+1,des,val+num[u]);
        dfs2(u+1,des,val);
      }
    }
    bool jud(long long val)
    {
      long long temp=0;
      int j=1;
      for(int i=tota;i>=0;i--)
      {
        if(vala[i]>val)  continue;
        for(;j<=totb&&vala[i]+valb[j]<=val;j++);
        temp+=j;
      }
      return temp>k;
    }
    void solve2()
    {
      dfs1(1,n/2,0);
      dfs2(n/2+1,n,0);
      sort(vala+1,vala+tota+1);
      sort(valb+1,valb+totb+1);
      long long l=0,r=0x3f3f3f3f3f3f3f3f;
      while(l<=r)
      {
        long long mid=(l+r)/2;
        if(jud(mid))  r=mid-1;
        else l=mid+1;
      }
      printf("%lld
    ",r+1);
    }
    int main()
    {
      scanf("%d%lld",&n,&k);
      for(int i=1;i<=n;i++)
        scanf("%lld",&num[i]);
      sort(num+1,num+n+1);
      long long j=0x3f3f3f3f3f3f3f3f;
      if(n>35)  solve1();
      else solve2();
    }  
  • 相关阅读:
    liunx 利用管道线kill多个进程
    将多个学生平均分配到多个学校的方法示例
    mysql 根据查询条件进行update
    Mysql 使用临时表比较数据差异以及 临时表的优化
    Netcore 将汉字转化为拼音
    mysql 清除多列重复数据,只保留其中一条
    使用Mysql 存储过程和游标进行同步数据
    Culture is not supported. (Parameter 'name') u0002� is an invalid culture identifier.
    Swagger 过滤特定控制器配置方法(Swashbuckle.AspNetCore 5.0.0)
    System.Linq Distinct 方法使用
  • 原文地址:https://www.cnblogs.com/AseanA/p/6603283.html
Copyright © 2011-2022 走看看