1. 程式人生 > >ZOJ 3726 Alice's Print Service(二分)

ZOJ 3726 Alice's Print Service(二分)

Alice’s Print Service Time Limit: 2 Seconds Memory Limit: 65536 KB Alice is providing print service, while the pricing doesn’t seem to be reasonable, so people using her print service found some tricks to save money.

For example, the price when printing less than 100 pages is 20 cents per page, but when printing not less than 100 pages, you just need to pay only 10 cents per page. It’s easy to figure out that if you want to print 99 pages, the best choice is to print an extra blank page so that the money you need to pay is 100 × 10 cents instead of 99 × 20 cents.

Now given the description of pricing strategy and some queries, your task is to figure out the best ways to complete those queries in order to save money.

Input The first line contains an integer T (≈ 10) which is the number of test cases. Then T cases follow.

Each case contains 3 lines. The first line contains two integers n, m (0 < n, m ≤ 105). The second line contains 2n integers s1, p1, s2, p2, …, sn, pn (0=s1 < s2 < … < sn ≤ 109, 109 ≥ p1 ≥ p2 ≥ … ≥ pn ≥ 0). The price when printing no less than si but less than si+1 pages is pi cents per page (for i=1…n-1). The price when printing no less than sn pages is pn cents per page. The third line containing m integers q1 … qm (0 ≤ qi ≤ 109) are the queries.

Output For each query qi, you should output the minimum amount of money (in cents) to pay if you want to print qi pages, one output in one line.

Sample Input 1 2 3 0 20 100 10 0 99 100 Sample Output 0 1000 1000

題意

列印店有n個區間,在每個區間內有一個列印價錢即 要列印的張數在[s1,s2)[s_1, s_2)內價錢為p1p_1,在[s2,s3)[s_2, s_3)內價錢為p

2p_2,當大於等於sns_n時價錢為pnp_n,題目保證si+1&gt;=sis_{i+1}&gt;=s_ipi&gt;=pi+1p_i&gt;=p_{i+1} 有m次詢問,每次詢問有一個要列印的總數,求每次詢問列印q張所需要的最小費用

思路

首先要知道q在哪一個sisi+1s_i\sim s_{i+1}內,所以直接二分就可以了找到這個區間就可以了,但是有可能往後面買更多的話反而比較便宜,所以我們可以從最後往前掃一遍,如果前一個的花費比後一個要大,那直接買下一個的張數就可以了,我們弄一個數組,從後掃存兩個乘積的較小值就可以了,然後比較一下只買q張和買後面的張數哪個更優就可以了

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1e5+5;
long long p[N];
long long s[N];
long long sum[N];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
        {
            scanf("%lld%lld",&s[i],&p[i]);
            sum[i]=s[i]*p[i];
        }
        for(int i=n-1;i>=0;i--)
        {
            if(sum[i-1]>sum[i])
                sum[i-1]=sum[i];
        }
        p[n]=1e9;
        s[n]=1e9;
        for(int i=0;i<m;i++)
        {
            long long x;
            scanf("%lld",&x);
            int pos=upper_bound(s,s+n,x)-s;
            long long ans=min(p[pos-1]*x,sum[pos]);
            if(pos==n)
                ans=x*p[n-1];
            printf("%lld\n",ans);
        }
    }
    return 0;
}