注意不是优先队列,因为优先队列只能对队头进行操作,所以……单调队列,从队头到队尾所有都可以操作
http://acm.hdu.edu.cn/showproblem.php?pid=4122
一开始把时间,什么年月日,转化为时间小时(开始搞错WA了一次)
后来使用单调队列,维护队列,使之到i 生产的最优,过期的出队列
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; char Month[13][9]={"","Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov" , "Dec"}; __int64 days[12]={31,28,31,30,31,30,31,31,30,31,30,31}; inline __int64 leap(__int64 year) { return ((year%4==0&&year%100!=0)||year%400==0); } struct DD { __int64 year,month,day,hour; }; __int64 data__int64(DD a) { __int64 ret=0;//(a.year-2000)*365+(a.year-2000)/4-(a.year-2000)/100+(a.year-2000)/400; int i; for(i=2000;i<a.year;i++) ret+=365+leap(i); days[1]+=leap(a.year); for(i=0;i<a.month-1;ret+=days[i++]); days[1]=28; return (ret+a.day-1)*24+a.hour+1; } struct data1 { __int64 hour; __int64 v; }need[100099]; struct data2 { __int64 ben; __int64 hour; }qq[100999]; __int64 cmp(data1 a,data1 b) { return a.hour<b.hour; } int main() { __int64 n,m; while(scanf("%I64d%I64d",&n,&m)) { if(n==0&&m==0)return 0; __int64 i,j,year,mon,day,time; char mm[9]; DD temp; for(i=1;i<=n;i++) { scanf("%s",mm); for(j=1;j<=12;j++) { if(strcmp(Month[j],mm)==0){ temp.month=j; break; } } scanf("%I64d%I64d%I64d",&temp.day,&temp.year,&temp.hour); __int64 temp1=need[i].hour=data__int64(temp); scanf("%I64d",&need[i].v); } sort(&need[1],&need[n+1],cmp); __int64 max,pri,cost; scanf("%I64d%I64d",&max,&pri); __int64 start,top,tail; top=tail=start=1; __int64 all=0; for(i=1;i<=m;i++) { scanf("%I64d",&cost); while(top<tail&&qq[tail-1].ben+(i-qq[tail-1].hour)*pri>=cost)tail--; qq[tail].ben=cost;qq[tail].hour=i;tail++; while(start<=n&&need[start].hour==i) { while((top<tail-1)&&(qq[top].hour+max<need[start].hour)) top++; __int64 temp=need[start].hour-qq[top].hour; all+=(qq[top].ben+(need[start].hour-qq[top].hour)*pri)*need[start].v; start++; } } printf("%I64d\n",all); } }