设在时间t有一个订单,要N个月饼,每个月饼每小时储存话费为S,设i时刻的制作单价为Vi,那么在i时刻(i>=t-T)去制作的花费为Vi*N+(T-i)*S*N
变形一下变成T*S*N+N*(Vi-i*S),这个等式中只有Vi-i*S和i的选取有关,所以实际上就是要找出在t[i]到t[i]-T范围内最大的Vi-i*S即可。用线段树实现。
算时间时一定要仔细写,把dec写成dev WA了 N次!
代码:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define maxn 100005 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define INF 10000000 #define LL long long LL V[maxn]; LL Min[maxn<<2]; LL Ord[maxn]; LL t[maxn]; int N,M,T,S; void pushup(int rt){ Min[rt]=min(Min[rt<<1],Min[rt<<1|1]); } void build(int l,int r,int rt){ if(l==r){ Min[rt]=V[l]; return; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } LL query(int L,int R,int l,int r,int rt){ if(L<=l&&R>=r) return Min[rt]; int m=(l+r)>>1; LL res=10000000; if(m>=L) res=min(res,query(L,R,lson)); if(m<R) res=min(res,query(L,R,rson)); return res; } bool isleapyear(int n){ return n % 4 == 0 && n % 100 != 0 || n % 400 == 0; } LL Time(char *m, int d, int y, int h){ LL res=0; for(int i=2000; i<y; i++){ if(isleapyear(i)) res += 366 * 24; else res += 365 * 24; } if(strcmp(m,"Jan")==0) res+=0; else if(strcmp(m,"Feb")==0) res+=31*24; else if(strcmp(m,"Mar")==0) res+=59*24; else if(strcmp(m,"Apr")==0) res+=90*24; else if(strcmp(m,"May")==0) res+=120*24; else if(strcmp(m,"Jun")==0) res+=151*24; else if(strcmp(m,"Jul")==0) res+=181*24; else if(strcmp(m,"Aug")==0) res+=212*24; else if(strcmp(m,"Sep")==0) res+=243*24; else if(strcmp(m,"Oct")==0) res+=273*24; else if(strcmp(m,"Nov")==0) res+=304*24; else if(strcmp(m,"Dec")==0) res+=334*24; res+=(d-1)*24; res+=h+1; if((isleapyear(y))&&(strcmp(m,"Jan")!=0)&&(strcmp(m,"Feb")!=0)){ res+=24; } return res; } int main(){ while(~scanf("%d%d",&N,&M)){ if(!N&&!M) break; for(int i=1;i<=N;i++){ char month[10]; int d,y,h,o; scanf("%s%d%d%d%d",month,&d,&y,&h,&o); t[i]=Time(month,d,y,h); Ord[i]=o; } scanf("%d%d",&T,&S); for(int i=1;i<=M;i++){ int tmp; scanf("%d",&tmp); V[i]=tmp-i*S; } build(1,M,1); LL res=0; for(int i=1;i<=N;i++){ LL s=(t[i]-T)>=1?(t[i]-T):1; if((t[i]-T)>M) continue; LL tmp=query(s,t[i],1,M,1); res+=(tmp+t[i]*S)*Ord[i]; } printf("%I64d\n",res); } return 0; }