题目链接: 传送门
题目大意:给你T组case,n组价格,m组查询 价格是按照这个意思给出的:先给数量然后给单价
查询就是给你多少张纸,查询最少花多少钱。
首先看见题目是准备这样来写:
从后向前搜一遍,对所给的每个临界点进行一个排序赋值:
比如:
0 20 【1】 0
100 10 【2】 1000
200 9 【3】 1800
300 7 【4】 2100
400 5 【5】 2000
拍完序之后就变成了相当于是特殊值的大小
【1】 0
【2】 1000
【3】 1800
【4】 2000
【5】 2000
下面就是特殊值与正常值大小的比较了
是一个二分的写法: upper_bound(s,s+n,x)-s;
返回的就是x在s函数中的向下取整的位置,其原理是运用了树,故是log(n)的查找时间
最后代码为何一直卡,是因为 我们用了cout的输出........本来以为case不多,cout也是可以过的后来T了真是tooyoung........
贴代码如下:
#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 100100
#define eps 1e-7
#define INF 0x7FFFFFFF
#define seed 131
#define unsigned long long ull;
#define lson l,m,rt<<1
#define rson r,m+1,rt<<1|1
long long s[MAXN],p[MAXN];
long long minm[MAXN];
int main()
{
long long n, m, i, j;
long long t;
long long x,ans;
scanf("%I64d",&t);
while(t--)
{
scanf("%I64d%I64d",&n,&m);
for(i=0; i<n; i++)
{scanf("%I64d%I64d",&s[i],&p[i]);}
minm[n-1] = s[n-1] * p[n-1];
for(i=n-2; i>=0; i--)
{
long long tt = s[i] * p[i];
minm[i] = min(tt,minm[i+1]);
}
for(i=0; i<m; i++)
{
scanf("%I64d",&x);
int pp = upper_bound(s,s+n,x)-s;
pp--;
if(pp==n-1)
{
ans = x * p[n-1];
}
else
ans = min(minm[pp+1],x*p[pp]);
printf("%I64d\n",ans);
}
}
return 0;
}