zoukankan      html  css  js  c++  java
  • 背包

    【问题描述】
    蛤布斯有 n 种商品,第 i 种物品的价格为 ai,价值为 bi。有 m 个人来向蛤
    布斯购买商品,每个人每种物品只能购买一个。第 j 个人有 cj 的钱,他会不停
    选择一个能买得起的价格最高的商品买走(如果有多个则选择价值最高的)。你
    需要求出每个人购买的物品的价值和。
    【输入格式】
    第一行两个正整数 n,m。接下来 n 行每行两个正整数 ai,bi。接下来 m 行
    每行一个正整数 cj。
    【输出格式】
    m 行,每行一个整数表示答案。
    【样例输入输出】
    pack.in
    5 4
    10 5
    9 8
    7 3
    3 4
    1 2
    20
    100
    28
    18
    pack.out
    15
    22
    18
    10
    【数据范围】
    对于 20%的数据,n,m<=1000。
    对于另外 30%的数据,ai,bi,cj 在[1,10^12]中均匀随机。
    对于 100%的数据,n,m<=100000,ai,bi,cj<=10^12。

    不能一个一个二分查找,因为有可能会全部都可以买,被卡掉

    排序是肯定的

    所以算出前缀和,每一次二分找到一个小于c的最大价格物品R

    再二分一个下界使得sum[R]-sum[L]<=c,然后把剩余价格递归

    可以证明递归次数<=logc

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long lol;
     7 struct FFF
     8 {
     9   lol a,b;
    10 }a[100001];
    11 lol sum[100001],sum2[100001],n,m;
    12 bool cmp(FFF a,FFF b)
    13 {
    14   return a.a<b.a||(a.a==b.a&&a.b<b.b);
    15 }
    16 int find1(int l,int r,lol x)
    17 {
    18   lol as=-1;
    19   while (l<=r)
    20     {
    21       int mid=(l+r)/2;
    22       if (a[mid].a<=x) as=mid,l=mid+1;
    23       else r=mid-1;
    24     }
    25   return as;
    26 }
    27 int find2(int l,int r,lol x)
    28 {
    29   lol as=-1;
    30   while (l<=r)
    31     {
    32       int mid=(l+r)/2;
    33       if (sum[mid]>=x) as=mid,r=mid-1;
    34       else l=mid+1;
    35     }
    36   return as;
    37 }
    38 lol count(int R,lol C)
    39 {
    40   lol s=0;
    41   int r=find1(1,R,C);
    42   if (r==-1) return 0;
    43   int l=find2(0,r-1,sum[r]-C);
    44     if (l!=-1)
    45       s+=sum2[r]-sum2[l];
    46     return s+count(l,C-sum[r]+sum[l]);
    47 }
    48 int main()
    49 {lol c,i;
    50   cin>>n>>m;
    51   for (i=1;i<=n;i++)
    52     {
    53       scanf("%lld%lld",&a[i].a,&a[i].b);
    54     }
    55   sort(a+1,a+n+1,cmp);
    56   for (i=1;i<=n;i++)
    57     sum[i]=sum[i-1]+a[i].a,sum2[i]=sum2[i-1]+a[i].b;
    58   for (i=1;i<=m;i++)
    59     {
    60       scanf("%lld",&c);
    61       printf("%lld
    ",count(n,c));
    62     }
    63 }
  • 相关阅读:
    公司的首页
    ubuntu 无法在Eclipse中识别 设备
    Eclipse 和 Android Studio 并存
    Eclipse 和 Android Studio 并存
    mac 节约硬盘空间
    一公升的眼泪
    Mac Ogre
    代码大全 是极好的
    Ogre Ubuntu 环境搭建
    cocos2d-x 环境搭建 c++ 版本
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7792999.html
Copyright © 2011-2022 走看看