2013长沙现场赛 Alice's Print Service

这个题是给出n个区间  每一个区间内部都有一个值。


输入一个数值。 求可能出现的最小值。  这个题明显的先是找到输入的这个值的所属于的区间。 找到这个区间就好写了。


但是看算法的数据大小来看。 区间个数的 10^5 个  输入的查找的个数 也是 10^5个。 如果直接爆的话  最慢的时间 是 10^10次搜索  必然会超时。


我一开始 以为是线段树。 点的区间查询。 确实可以这么做。 但是更简单的是办法是 二分。 因为 区间是连续递增的。


那么直接可以二分 就可以找到 一个点 属于哪个位置了。 


这里面有个坑。  最后一个区间的值 也可能是 所有区间的最小值。 那这就需要 来一次动规 更新一下所有区间的最小值。 然后就好做了。


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <fstream>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <list>
#include <vector>
#include <cmath>
#include <iomanip>
typedef long long LL;
typedef unsigned long long LLU;
const double PI=acos(-1.0);
using namespace std;
#define MAXN 100000+10
LL s[MAXN],p[MAXN];
LL minn[MAXN];
int main (){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        memset(s,0,sizeof(s));
        memset(p,0,sizeof(p));
        memset(minn,0,sizeof(minn));
        for(int i = 0; i < n; i++){
            scanf("%I64d%I64d",&s[i],&p[i]);
            minn[i] = (s[i]*p[i]);
        }
        for(int i = n-2; i >= 0; i--)
            minn[i] = min(minn[i], minn[i+1]);
        for(int i = 0; i < m; i++){
            LL w;
            scanf("%I64d",&w);
            int wh = upper_bound(s,s+n,w) - s;
            if(wh == n)
                printf("%I64d\n",(p[n-1]*w));
            else
                printf("%I64d\n",min((p[wh-1]*w),minn[wh]));
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值