我们发现先打印的时候如果不是需要多少打印多少,那么最优解一定是打印一个分界点那么多份,因为少打一份不合算,多打一份是浪费。这就很容易解决了,首先由于没有更新,只有询问,我们可以离线操作。首先统一预处理,用v[ i ]记录,打印s[ i ]这么多份时,最少花费多少钱。然后二分找到第一个大于等于需要打印的份数的标号,算出本来需要多少钱,和v[pos]取一个小,就是答案。最坑的是G++会TLE,C++才能过= =。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAX = 200010;
LL s[MAX], p[MAX], v[MAX];
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
int n, m;
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++){
scanf("%lld%lld",&s[i],&p[i]);
}
for(int i=n-1; i>=0; i--){
if(i == n - 1)
v[i] = s[i] * p[i];
else
v[i] = min(v[i+1], s[i] * p[i]);
}
for(int i=0; i<m; i++){
int x;
scanf("%d",&x);
int pos = lower_bound(s, s + n, x) - s;
LL ans = x * p[pos - 1];
if(pos < n) ans = min(ans, v[pos]);
printf("%lld\n",ans);
}
}
return 0;
}