JZOJ5440. 【NOIP2017提高A组冲刺11.1】背包

来源:互联网 发布:cocos2d.js sdk 编辑:程序博客网 时间:2024/06/05 06:50

Description

蛤布斯有n种商品,第i种物品的价格为ai,价值为bi。有m个人来向蛤布斯购买商品,每个人每种物品只能购买一个。第j个人有cj的钱,他会不停选择一个能买得起的价格最高的商品买走(如果有多个则选择价值最高的)。你需要求出每个人购买的物品的价值和。

Input

第一行两个正整数n,m。接下来n行每行两个正整数ai,bi。接下来m行每行一个正整数cj。

Output

m行,每行一个整数表示答案。

Sample Input

5 4
10 5
9 8
7 3
3 4
1 2
20
100
28
18

Sample Output

15
22
18
10

Data Constraint

20%的数据,n,m<=1000。
30%的数据,ai,bi,cj在[1,10^12]中均匀随机。
100%的数据,n,m<=100000,ai,bi,cj<=10^12。

题解

很容易就想到二分,
先对所有的物品排好序,
每次二分应该最大的来去。
这样看似是一个很不错的解法,
然而并不是,
这个时间复杂度跟取了多少个物品有关,
通过特殊构造的数据,即每个物品都要取,或者取的物品很多,
这样这种解法就会很慢。

当取了一个物品之后,下一个物品就应该在它的后面,
假设金钱很多的时候,一定是会连着取,
这样就再二分多应该东西,可以连续取多少个。

这样每次处理之后金钱都会减半,最多就logn次。

code

#include <iostream>#include <cstdio>#include <cmath>#include <string.h>#include <algorithm>#define ll long long#define N 100003using namespace std;char ch;void read(ll& n){    n=0;    ch=getchar();    while(ch<'0'||ch>'9')ch=getchar();    while('0'<=ch && ch<='9')n=(n<<1)+(n<<3)+ch-'0',ch=getchar();}void write(ll x){    if(x>9)write(x/10);    putchar(x%10+48);}struct node{    ll x,y;}t[N];bool cmp(node a,node b){    return a.x>b.x ||(a.x==b.x && a.y>b.y);}ll n,m,x,l,r,ans,mid,s[N],f[N],st,ls;int main(){    freopen("pack.in","r",stdin);    freopen("pack.out","w",stdout);    read(n);read(m);    for(int i=1;i<=n;i++)        read(t[i].x),read(t[i].y);    sort(t+1,t+1+n,cmp);    for(int i=1;i<=n;i++)        s[i]=s[i-1]+t[i].x,f[i]=f[i-1]+t[i].y;    for(int i=1;i<=m;i++)    {        read(x);        ans=0;l=0;        while(x>0)        {            r=n+1;l++;            while(l<r)            {                mid=(l+r)>>1;                if(t[mid].x>x)l=mid+1;else r=mid;            }            if(r==n+1)break;            st=l;            r=n;            while(l<=r)            {                mid=(l+r)>>1;                if(s[mid]-s[st-1]<=x)l=mid+1,ls=mid;else r=mid-1;            }            x-=s[ls]-s[st-1];ans+=f[ls]-f[st-1];        }        write(ans);        putchar('\n');    }    return 0;}
原创粉丝点击