题意: 打印东西,给出区间(张数)对应费用(到达一定张数就都按某更低的价格),m次询问,问最优费用。给的时候按张数递增给的。
dp出当前张数到最后的最小值。对于询问q,然后二分处》=q的最小的一个张数的价格。min(这个价格*p,dp[这+1])即可。nlogn;后来看网上有些人用线段树,没必要的。
ps:开始竟然因为犯中间数据爆int的初级错误!,不该不该!
#include<iostream> #include<vector> #include<algorithm> #include<cstdio> using namespace std; struct node { long long si; long long pi; long long pay; }; long long dp[100005]; node v[100008]; int n,m; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%d%d",&v[i].si,&v[i].pi); v[i].pay=v[i].si*v[i].pi; } dp[n-1]=v[n-1].pay; for(int i=n-2;i>=0;i--) { dp[i]=min(v[i].pay,dp[i+1]); } int x; while(m--) { scanf("%d",&x); int r=n,l=0,mid; while(l+1<r) { mid=(r+l)/2; if(v[mid].si>x) { r=mid; } else { l=mid; } } long long ans=v[l].pi*x; if(l+1<n&&dp[l+1]<ans) ans=dp[l+1]; printf("%I64d\n",ans); } } return 0; }
时间: 2024-10-05 05:32:28