HDU4791【杂】

题意:

给你一个从0开始的区间si,每个区间是前闭后开,[ s[i] , s[i+1] ), 然后再给你个一个pi,代表你在区间[ s[i] , s[i+1] )里面买东西的单价是pi,给出的s1一定是0,给出的顺序是s1,p1,s2,p2...sk,pk,...sn,pn。然后给你个m个值,然后计算买了>=b[m]个物品需要花费的最少值;

思路:

预处理一下,买si个物品需要的花费,用个数组存一下从当前si量开始的最小花费,然后对于给入的值二分找一下他所在的区间[ s[i] , s[i+1] ),然后比较一下s[i+1]的最小和pi*给入的值的大小;注意是>=sn的时候;

贴一发比赛时的挫代码,一开始就瞎几把想其实预处理一下当前到最后的最小就行了。所以打的那么挫;

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N=1e5+10;

int n;
LL flag[N];

struct node
{
    LL x;
    LL y;
};
node qujian[N];

struct asd
{
    LL page;
    LL w;
};
asd q[N];

bool cmp1(node p1,node p2)
{
    return p1.x<p2.x;
}

int main()
{
    int n,m;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
        {
            scanf("%lld%lld",&qujian[i].x,&qujian[i].y);
            q[i].w=qujian[i].x*qujian[i].y;
        }
        sort(qujian+1,qujian+n+1,cmp1);
        LL temp=q[n].w;
        flag[n]=temp;
        for(int i=n-1; i>=1; i--)
        {
            if(temp>q[i].w)
                temp=q[i].w;
            flag[i]=temp;
        }

//        for(int i=1;i<=n;i++)
//            printf("%lld ",flag[i]);
//        puts("");

        while(m--)
        {
            LL tmp;
            scanf("%lld",&tmp);
            int left=1;
            int right=n;
            while(left<right)
            {
                int mid=left+(right-left+1)/2;
                if(qujian[mid].x<=tmp)
                    left=mid;           //一定会变大
                else
                    right=mid-1;    //一定会变小
            }
            left++;
//            printf("%d
",left);
            if(left>n)
                printf("%lld
",qujian[left-1].y*tmp);
            else
                printf("%lld
",(qujian[left-1].y*tmp)<flag[left]?(qujian[left-1].y*tmp):flag[left]);
        }
    }
    return 0;
}

/*
100
2 100
0 20 100 10
0 99 100
*/


原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6216773.html