qut1353yeweiyang的打印服务(二分)

来源:互联网 发布:单片机模拟仿真软件 编辑:程序博客网 时间:2024/06/06 19:58


来源:青岛理工交流赛的A题。

QUT的yeweiyang最近想做点小生意,几经调研他决定通过提供打印
服务来赚钱。但是这个打印机服务有点小bug,聪明的QUT同学们
发现了这个打印服务的漏洞,于是乎他们都到来yeweiyang这里
打印,一时间yeweiyang的生意非常红火。
漏洞是这样的,举个例子来说,当打印少于100张纸的时候,每张2毛钱。但是当
打印大于等于100张的时候,每张你只用付1毛钱。很容易看出
如果你想要打印99张纸,最好的选择是,你多打印一张白纸,
这样你需要花的钱是 100 * 1 毛钱。而不是 99 * 2毛钱。
现在给你打印策略的描述,以及一些询问,

你的任务是针对这些询问,输出最少的消费。

输入

第一行一个T代表组数。 T<20
每组输入三行。第一行包含两个整数 n ,m( 0<n,m<10^5)
第二行包含 2 * n 个整数 s1 ,p1, s2 ,p2,,,,sn,pn
(0 = s1 <s2 <...<sn<= 10^9 , 10^9 >=p1 >=p2>=...>=pn>=0)
页数大于等于 si ,但是小于 s(i+1)的时候,每张花费pi
页数大于等于 sn 的 每张花费pn.
第三行包含m个整数 q1,....qm ( 0<=qi<=10^9),对应m次询问

输出

对于每个询问qi,你应该输出打印qi张纸的最小花费,每个询问输出一行

样例输入

12 30 20 100 100 99 100

样例输出

010001000

分析:

最简单的思路是我先通过O(n)来搜索到恰好等于q的sn然后再计算之后所有的sn*pn取最小值,显然这样会超时复杂度是O(nm)这里采取两个措施,通过二分搜索直接搜到恰好小于或等于q的sn,那么假如我们还是直接去算后面所有的sn*pn肯定要超时,我们这里可以预处理一下(从后往前预处理)。用一个cost数组来存,比如cost存储的是后面si*pi的最小值,很明显这是处理完之后cost数组是单调递增的,可以用O( n)的时间预处理,通过这两个我们可以发现复杂度已经是O(n+mlogn)这就是满足题意的算法了。

其实对于cost数组单调递增的现实意义理解就是,我多买可以省钱那为什么不多买呢,就是用多买的情况把前面比自己花费高的给降了下来。


#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int maxn = 100005;long long s[maxn], p[maxn], cost[maxn];int main(){    int T, n, m;    scanf("%d", &T);    while(T--)    {        scanf("%d%d", &n, &m);        for(int i = 0; i < n; i++)        {            scanf("%I64d%I64d", &s[i], &p[i]);            cost[i] = s[i] * p[i];        }        for(int i = n - 2; i >= 0; i--)            cost[i] = min(cost[i+1], cost[i]);        long long q, ans;        for(int i = 0; i < m; i++)        {            scanf("%I64d", &q);            int left = 0, right = n - 1, mid, id;            while(left <= right)            {                mid = (left + right) / 2;                if(q > s[mid])                {                    id = mid;                    left = mid + 1;                }                else if(q < s[mid])                {                    right = mid - 1;                }                else                {                    id = mid;                    break;                }            }            ans = q * p[id];            if(id +1 <= n-1)                ans = min(ans, cost[id+1]);            printf("%lld\n", ans);        }    }    return 0;}


1 0
原创粉丝点击