这个题是给出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;
}