题目大意:一个月饼店开m个小时(24小时营业),只在整点做月饼,做月饼的能力非常强。现在只需要考虑成本的问题。给m个cost值,cost[i]表示第i个小时做1个月饼的代价。
再给n个时间,从2000年1月1日0时开始计算。表示订单的截止时间。当然为了节约成本,可以提前趁成本不高的时候做月饼。但是月饼有保质期,t天,月饼放冰箱保存也需要代价,一天花费s。现在求完成n个订单最小代价。
题目分析:对于第i个订单,首先计算出是第ti个营业时间。这里考虑每个月饼的单价。所以第i个订单的月饼只能在(ti - t,ti]做。考虑时间j有个订单,假设时间i完成代价是最小的。那么第j个订单的代价就是cost[i] + (j - i) * s,整理一下:cost[i] - i*s + j*s,这里我们只需要维护cost[i] - i*s即可。即维护(订单时间-t,订单时间]这个区间里的cost[i] - i*s的最小值即可。所以可以用单调队列或者线段树来维护。
线段树:
RMQ:
线段树:
//hdu4122Alice's mooncake shop(单调队列 | 线段树)
#include<stdio.h>
#include<string>
#include<map>
#define LL long long int
#define inf 0x7f7f7f7f
#define MAX 100009
using namespace std;
struct Node{
char str[10];
LL a,b,c,x,hour;
}mapp[3000];
LL cost[100009];
map<string,int> month;
LL minV;
LL n,m,T,S;
int mon[]={31,28,31,30,31,30,31,31,30,31,30,31};//每个月的天数
struct point{
LL minV;
LL maxV;
LL L;
LL R;
LL mid(){
return (L+R)/2;
}
}tree[MAX*4];
void build(LL root, LL s,LL e){
tree[root].L=s;
tree[root].R=e;
tree[root].minV=inf;
if(tree[root].L!=tree[root].R){
build(root*2,s,tree[root].mid());
build(root*2+1,tree[root].mid()+1,e);
}
}
//cost[i] - i*s
void insert(LL root, LL pos, LL val){
if(tree[root].L==tree[root].R){
tree[root].minV=val;
return;
}
if(pos<=tree[root].mid()){
insert(root*2, pos, val);
}else{
insert(root*2+1,pos,val);
}
tree[root].minV=min(tree[root*2].minV,tree[root*2+1].minV);
}
void query(LL root, LL s, LL e){
if(tree[root].L==s&&tree[root].R==e){
minV=min(tree[root].minV,minV);
return ;
}
if(e<=tree[root].mid()){
query(root*2,s,e);
}else if(s>tree[root].mid()){
query(root*2+1,s,e);
}else{
query(root*2,s,tree[root].mid());
query(root*2+1,tree[root].mid()+1,e);
}
}
bool isleap(int t){
if(t%400==0||(t%100!=0&&t%4==0)) return true;
return false;
}
LL gettime(int t){
LL day=0;
for(int i=2000;i<mapp[t].b;i++){
if(isleap(i)){
day+=366*24;
}else {
day+=365*24;
}
}
int tmp=month[mapp[t].str];
for(int i=0;i<tmp;i++){
if(isleap(mapp[t].b)&&i==1){
day+=24;
}
day+=mon[i]*24;
}
day+=(mapp[t].a-1)*24;
day+=mapp[t].c;
return day;
}
int main(){
month["Jan"]=0;
month["Feb"]=1;
month["Mar"]=2;
month["Apr"]=3;
month["May"]=4;
month["Jun"]=5;
month["Jul"]=6;
month["Aug"]=7;
month["Sep"]=8;
month["Oct"]=9;
month["Nov"]=10;
month["Dec"]=11;
while(~scanf("%I64d %I64d",&n,&m),n+m!=0){
for(int i=0;i<n;i++){
scanf("%s",mapp[i].str);
scanf("%I64d %I64d %I64d %I64d",&mapp[i].a,&mapp[i].b,&mapp[i].c,&mapp[i].x);
mapp[i].c+=1;
//month date year H R
//Jan 1 2000 9 10
mapp[i].hour=gettime(i);
}
scanf("%I64d %I64d",&T,&S);
build(1,1,m);
for(int i=1;i<=m;i++){
scanf("%I64d",&cost[i]);
//cost[i] - i*s
cost[i]-=i*S;
insert(1,i,cost[i]);
}
LL ans=0;
for(int i=0;i<n;i++){
LL tmp=mapp[i].hour-T;
if(tmp<1) tmp=1;
minV=inf;
query(1,tmp,mapp[i].hour);
ans+=mapp[i].x*(minV+mapp[i].hour*S);
}
printf("%I64d\n",ans);
}
return 0;
}
RMQ:
//hdu4122Alice's mooncake shop(单调队列 | 线段树)
#include<stdio.h>
#include<string>
#include<map>
#include<algorithm>
#define LL long long int
#define inf 0x7f7f7f7f
#define MAX 100009
using namespace std;
struct Node{
char str[10];
LL a,b,c,x,hour;
}mapp[3000];
LL cost[100009];
map<string,int> month;
LL minV;
LL n,m,T,S;
LL dp[100009][20];
int mon[]={31,28,31,30,31,30,31,31,30,31,30,31};//每个月的天数
bool isleap(int t){
if(t%400==0||(t%100!=0&&t%4==0)) return true;
return false;
}
LL gettime(int t){
LL day=0;
for(int i=2000;i<mapp[t].b;i++){
if(isleap(i)){
day+=366*24;
}else {
day+=365*24;
}
}
int tmp=month[mapp[t].str];
for(int i=0;i<tmp;i++){
if(isleap(mapp[t].b)&&i==1){
day+=24;
}
day+=mon[i]*24;
}
day+=(mapp[t].a-1)*24;
day+=mapp[t].c;
return day;
}
/*
void initRMQ(int n)
{
mm[0] = -1;
for(int i = 1;i <= n;i++)
{
mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
dp[i][0] = b[i];
}
for(int j = 1;j <= mm[n];j++)
for(int i = 1;i + (1<<j) - 1 <= n;i++)
dp[i][j] = min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
long long rmq(int x,int y)
{
int k = mm[y-x+1];
return min(dp[x][k],dp[y - (1<<k) + 1][k]);
}
*/
void RMQ_init(){
for(int i=1;i<=m;i++){
dp[i][0]=cost[i];
// printf("%I64d ",dp[i][0]);
}
//puts("");
for(int j=1;(1<<j)<=m;j++){
for(int i=1;i+(1<<j)-1<=m;i++){
dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
//printf("%d %d %I64d\n",i,j,dp[i][j]);
}
//puts("");
}
}
LL RMQ(int L,int R){
int k=0;
while((1<<(k+1)) <=(R-L+1)) k++;
return min(dp[L][k],dp[R-(1<<k)+1][k]);
}
int main(){
month["Jan"]=0;
month["Feb"]=1;
month["Mar"]=2;
month["Apr"]=3;
month["May"]=4;
month["Jun"]=5;
month["Jul"]=6;
month["Aug"]=7;
month["Sep"]=8;
month["Oct"]=9;
month["Nov"]=10;
month["Dec"]=11;
while(~scanf("%I64d %I64d",&n,&m),n+m!=0){
for(int i=0;i<n;i++){
scanf("%s",mapp[i].str);
scanf("%I64d %I64d %I64d %I64d",&mapp[i].a,&mapp[i].b,&mapp[i].c,&mapp[i].x);
mapp[i].c+=1;
//month date year H R
//Jan 1 2000 9 10
mapp[i].hour=gettime(i);
}
scanf("%I64d %I64d",&T,&S);
for(int i=1;i<=m;i++){
scanf("%I64d",&cost[i]);
//cost[i] - i*s
cost[i]-=i*S;
}
RMQ_init();
LL ans=0;
for(int i=0;i<n;i++){
LL tmp=mapp[i].hour-T;
if(tmp<1) tmp=1;
ans+=mapp[i].x*(RMQ(tmp,mapp[i].hour)+mapp[i].hour*S);
}
printf("%I64d\n",ans);
}
return 0;
}