/**
hdu 4122 单调队列
题目大意:给定n个时刻,在每一个时刻都要生产ai个月饼。给出m个可以生产的时刻,每个时刻单个生产费用为bi,单个月饼可储存T时间,单位时间费用为S
问如何安排生产花费最少
解题思路:用单调队列维护一个点之前所有点的最小花费(为生产费+储存费)
特别注意:n个时刻可能有重复的
*/
using namespace std;
typedef long long LL;
mapint>mp;
int n,m,time[3050],sum[15],S,T,cost[100050],q[100050];
LL num[3000];
void init()
{
mp["Jan"]=1,mp["Feb"]=2,mp["Mar"]=3,mp["Apr"]=4,mp["May"]=5,mp["Jun"]=6,mp["Jul"]=7,mp["Aug"]=8;
mp["Sep"]=9,mp["Oct"]=10,mp["Nov"]=11,mp["Dec"]=12;
sum[0]=0,sum[1]=31,sum[2]=sum[1]+28,sum[3]=sum[2]+31,sum[4]=sum[3]+30,sum[5]=sum[4]+31,sum[6]=sum[5]+30;
sum[7]=sum[6]+31,sum[8]=sum[7]+31,sum[9]=sum[8]+30,sum[10]=sum[9]+31,sum[11]=sum[10]+30;
}
int get(int y,int m,int d,int t)
{
int ans=0;
for(int i=2000; i<y; i++)
{
if((i%4==0&&i%100!=0)||i%400==0)
ans+=366;
else
ans+=365;
}
if((y%4==0&&y%100!=0)||y%400==0)
{
ans+=sum[m-1];
if(m-1>=2)ans++;
}
else
{
ans+=sum[m-1];
}
ans+=(d-1);
return ans*24+t;
}
int main()
{
init();
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)break;
for(int i=0; iint year,day,t;
char mon[10];
scanf("%s%d%d%d%I64d",mon,&day,&year,&t,&num[i]);
time[i]=get(year,mp[mon],day,t);
//printf("->%d\n",time[i]);
}
scanf("%d%d",&T,&S);
int tail=0,head=0,k=0;
LL cnt=0;
for(int i=0; i<m; i++)
{
scanf("%d",&cost[i]);
while(headq[tail-1]]+S*(i-q[tail-1])>=cost[i])tail--;
q[tail++]=i;
while(i==time[k])
{
while(head+1q[head]>T))head++;
//printf("%d==>>%d\n",i,q[head]);
cnt+=num[k]*(cost[q[head]]+S*(i-q[head]));
k++;
}
}
printf("%I64d\n",cnt);
}
return 0;
}
/**
2 10
Jan 1 2000 2 10
Jan 1 2000 9 10
5 2
20
20
20
10
10
8
7
9
5
10
0 0
*/
思路分析:
ans = segma( num[]*(cost[] + (i-j)*s) )
整理一下会发现式子就是
cost[]-j*s + i*s
对于每一个订单,我们把i拿出来分析
所以也就用cost - j*s 建树。
然后在储存期间找到最小的花费就行了。
#include
#include
#include
#include
#include
#define lson num<<1,s,mid
#define rson num<<1|1,mid+1,e
#define maxn 2555
#define maxm 100005
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
int n,m;
int days[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31}};
string tab[] = {"","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
LL tre[maxm<<2];
int getmonth(string x)
{
for(int i=1;i<=12;i++)
if(x==tab[i])return i;
}
bool leap(int x)
{
if(((x%4==0) && x%100!=0) || x%400==0)return true;
return false;
}
LL gethour(int month,int day,int year,int hour)
{
LL res=day-1;
int is=leap(year);
for(int i=1;ifor(int i=2000;i365+leap(i);
res*=24;
res+=hour+1;
return res;
}
void build(int num,int s,int e)
{
tre[num]=inf;
if(s==e)return;
int mid=(s+e)>>1;
build(lson);
build(rson);
}
void update(int num,int s,int e,int pos,LL val)
{
if(s==e)
{
tre[num]=val;
return;
}
int mid=(s+e)>>1;
if(pos<=mid)update(lson,pos,val);
else update(rson,pos,val);
tre[num]=min(tre[num<<1],tre[num<<1|1]);
}
LL query(int num,int s,int e,int l,int r)
{
if(l<=s && r>=e)
{
return tre[num];
}
int mid=(s+e)>>1;
if(r<=mid)return query(lson,l,r);
else if(l>mid)return query(rson,l,r);
else return min(query(lson,l,mid),query(rson,mid+1,r));
}
string tmp;
LL num[maxn];
LL cost[maxm];
LL time[maxm];
int main()
{
while(cin>>n>>m)
{
if(n==0 && m==0)break;
for(int i=1;i<=n;i++)
{
int d,y,h,Num;
cin>>tmp;
cin>>d>>y>>h>>Num;
num[i]=Num;
time[i]=gethour(getmonth(tmp),d,y,h);
}
LL S,T;
build(1,1,m);
cin>>T>>S;
for(int i=1;i<=m;i++)
{
cin>>cost[i];
cost[i]-=i*S;
update(1,1,m,i,cost[i]);
}
LL ans=0;
for(int i=1;i<=n;i++)
{
if(time[i]>m)break;
ans+=num[i]*(query(1,1,m,max(1LL,time[i]-T+1),time[i])+time[i]*S);
}
cout<return 0;
}