这道题要用到单调队列,我们从给出的样例能够看出,区间上很长的一段对当前的决策来说是毫无意义的,最明显的就是比当前的值大的那些值,其实这个也有一点动态规划的思想在里面,我们保证了队首位置的值对当前来说是最优的,很显然这肯定是一个递增的队列,对于当前要加入队列中的元素,我们去掉对于其来说毫无意义的一些值,对于队列中的一个位置i如果其后的一个位置的j的最优值取在了i的位置,也就意味着cost[j]>cost[i]+(j-i)*S,那么对于其后的一个位置k如果有cost[j]+(k-j)*S<cost[k]不等式相加我们可以得到cost[k]>cost[i]+(k-i)*S,而且我们假设cost[j]-cost[i]-(j-i)*S=m以及cost[k]-cost[j]-(k-j)*S=n则cost[k]-cost[i]-(k-i)*S=m+n也就是说队列里的元素从队首至当前要插入的位置对于k来说的优先级别是递减的。也就是说,队首元素就是最优的元素。
View Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define M 3000 5 #define N 100005 6 using namespace std; 7 _int64 que[N]; 8 _int64 id[N]; 9 _int64 val[M]; 10 _int64 t[M]; 11 char mon[12][5]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; 12 _int64 getmon(char *s) 13 { 14 _int64 i; 15 for(i=0;i<12;i++) 16 if(!strcmp(s,mon[i])) 17 return i; 18 } 19 _int64 day[12]={31,28,31,30,31,30,31,31,30,31,30,31}; 20 bool is(_int64 year) 21 { 22 if(year%400==0||(year%100&&year%4==0)) 23 return true; 24 return false; 25 } 26 _int64 alltime(_int64 year,_int64 month,_int64 date,_int64 hour) 27 { 28 _int64 i,j; 29 _int64 ans=0; 30 for(i=2000;i<year;i++) 31 { 32 if(is(i)) 33 ans+=366; 34 else 35 ans+=365; 36 } 37 for(i=0;i<month;i++) 38 { 39 if(is(year)&&i==1) 40 ans+=29; 41 else 42 ans+=day[i]; 43 } 44 ans+=(date-1); 45 ans*=24; 46 ans+=hour; 47 return ans; 48 } 49 int main() 50 { 51 char mo[5]; 52 _int64 n,m; 53 _int64 year,date,hour,month; 54 _int64 S,cost,T; 55 _int64 ans; 56 _int64 i; 57 while(scanf("%I64d%I64d",&n,&m)&&(n||m)) 58 { 59 for(i=0;i<n;i++) 60 { 61 scanf("%s%I64d%I64d%I64d%I64d",mo,&date,&year,&hour,&val[i]); 62 month=getmon(mo); 63 t[i]=alltime(year,month,date,hour); 64 } 65 scanf("%I64d%I64d",&T,&S); 66 _int64 top,tail; 67 _int64 fir; 68 top=tail=fir=0; 69 ans=0; 70 for(i=0;i<m;i++) 71 { 72 scanf("%I64d",&cost); 73 while(top<tail&&(que[tail-1]+(i-id[tail-1])*S)>=cost) 74 tail--; 75 que[tail]=cost; 76 id[tail++]=i; 77 while(fir<n&&t[fir]==i) 78 { 79 while(top<tail-1&&id[top]+T<t[fir]) 80 top++; 81 ans+=val[fir]*(que[top]+(t[fir]-id[top])*S); 82 fir++; 83 } 84 } 85 printf("%I64d\n",ans); 86 } 87 return 0; 88 }