zoukankan      html  css  js  c++  java
  • 【YbtOJ#20071】礼物购买

    题目

    题目链接:http://noip.ybtoj.com.cn/problem/20071

    思路

    (sum[i]) 表示按价格从大到小排序之后前 (i) 个物品的价格和。
    然后假设当前有 (w) 元,要从第 (i) 个物品开始买,二分出第一个 (j) 使得 (sum[j]-sum[i-1]leq w),然后将 (isim j) 全部买下,剩余钱买尽量多的 (j+1)
    加下来再次二分出第一个可以买的物品 (i'),继续上述操作即可。
    假设我们有 (w) 元后一次操作变成了 (w') 元,当买的最后一个物品价格超过 (frac{w}{2}) 时,(w') 显然不超过 (w-) 价格,所以 (w'<frac{w}{2});当最后一个物品价格不超过 (frac {w}{2}) 时,因为买了最后一个物品之后买不了下一个物品了,所以剩余的钱一定不超过最后一个物品的价格,也就有 (w'leq frac{w}{2})
    所以上述循环只会进行 (O(log w)) 次,时间复杂度 (O(mlog nlog w))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=100010;
    int n,m,ans,cnt[N];
    ll w,sum[N],b[N];
    
    struct node
    {
    	ll v,x;
    }a[N];
    
    bool cmp(node x,node y)
    {
    	return x.v>y.v;
    }
    
    int main()
    {
    	freopen("present.in","r",stdin);
    	freopen("present.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%lld%lld",&a[i].v,&a[i].x);
    		b[i]=a[i].v;
    	}
    	sort(b+1,b+1+n);
    	sort(a+1,a+1+n,cmp);
    	for (int i=1;i<=n;i++)
    	{
    		sum[i]=sum[i-1]+a[i].x*a[i].v;
    		cnt[i]=cnt[i-1]+a[i].x;
    	}
    	sum[n+1]=b[n+1]=a[n+1].v=1e18;
    	while (m--)
    	{
    		scanf("%lld",&w);
    		ans=0;
    		for (int i=1;i<=n;)
    		{
    			int r=upper_bound(sum+1,sum+2+n,sum[i-1]+w)-sum;
    			w-=sum[r-1]-sum[i-1]; ans+=cnt[r-1]-cnt[i-1];
    			ans+=w/a[r].v; w%=a[r].v;
    			i=n-(upper_bound(b+1,b+n-r+1,w)-b-1)+1;
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    ORACLE(系统表emp) 基本与深入学习
    jQuery框架 的四个入口函数
    函数
    sql1999语法
    左连接,右连接
    Oracle单行函数用法
    Kettle
    order by 排序
    sql*plus
    sql基本语句
  • 原文地址:https://www.cnblogs.com/stoorz/p/13879494.html
Copyright © 2011-2022 走看看