题目链接:
HDU:http://acm.hdu.edu.cn/showproblem.php?pid=4791
ZJU:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5072
1 2 3 0 20 100 10 0 99 100
0 1000 1000
题意:
打印纸张,随着张数的添加,每张的价格非递增,给出 m 个询问打印的张数,求出最小的花费。
PS:
保留打印a[i]份分别须要的钱,从后往前扫一遍,保证取得最优解。
然后再找到所打印的张数的区间,与没有多打印,仅仅打印m张所需的花费比較!
HDU代码例如以下:
#include <cstdio> #include <cstdlib> #include <algorithm> #include <vector> #include <iostream> #define INF 1e18 using namespace std; const int maxn=100017; typedef __int64 LL; LL s[maxn],p[maxn],c[maxn]; int main() { int T; int n, m; LL tt; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i = 0; i < n; i++) { scanf("%I64d%I64d",&s[i],&p[i]); } LL minn = INF; for(int i = n-1; i >= 0; i--) { minn = min(s[i]*p[i],minn); c[i] = minn; } for(int i = 0; i < m; i++) { scanf("%I64d",&tt); if(tt>=s[n-1])//最后 printf("%I64d\n",tt*p[n-1]); else { int pos = upper_bound(s,s+n,tt)-s; LL ans = tt*p[pos-1]; ans = min(ans,c[pos]); printf("%I64d\n",ans); } } } return 0; }
ZJU代码例如以下:
#include <cstdio> #include <algorithm> #include <iostream> #define INF 1e18 using namespace std; const int maxn = 100017; typedef long long LL; LL s[maxn], p[maxn], c[maxn]; int main() { int T; int n, m; LL tt; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i = 0; i < n; i++) { scanf("%lld%lld",&s[i],&p[i]); } LL minn = INF; for(int i = n-1; i >= 0; i--) { minn = min(s[i]*p[i],minn); c[i] = minn; } for(int i = 0; i < m; i++) { scanf("%lld",&tt); if(tt>=s[n-1])//最后 printf("%lld\n",tt*p[n-1]); else { int pos = upper_bound(s,s+n,tt)-s; LL ans = tt*p[pos-1]; ans = min(ans,c[pos]); printf("%lld\n",ans); } } } return 0; }