单调队列
正式由于每个月饼可以保存T小时,转化为滑动窗口,不超过T(这里我认为是T+1,即第i小时生产的月饼,i+T小时仍然可以用,所以T+1个小时)的窗口的最小值。
队列的初始化很重要,wa了好久。
#include <iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 1e5 + 5;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int M[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int a[N],time[N],b[N];
int S, T;
int n, m;
int q[N];
int MON(char *m){
if (strcmp(m, "Jan") == 0)return 1;
if (strcmp(m, "Feb") == 0)return 2;
if (strcmp(m, "Mar") == 0)return 3;
if (strcmp(m, "Apr") == 0)return 4;
if (strcmp(m, "May") == 0)return 5;
if (strcmp(m, "Jun") == 0)return 6;
if (strcmp(m, "Jul") == 0)return 7;
if (strcmp(m, "Aug") == 0)return 8;
if (strcmp(m, "Sep") == 0)return 9;
if (strcmp(m, "Oct") == 0)return 10;
if (strcmp(m, "Nov") == 0)return 11;
return 12;
}
bool LeapYear(int &year){
return year % 4 == 0 && year % 100 || year % 400 == 0;
}
int Time(int year, int Mon, int d, int h){
int t = 0;
for (int i = 2000; i<year; ++i){
if (LeapYear(i))t += 366;
else t += 365;
}
bool flag = LeapYear(year);
for (int i = 1; i<Mon; ++i){
if (flag && i == 2)t += 29;
else t += M[i];
}
t += d - 1;
return t * 24 + h;
}
int main()
{
while (scanf("%d%d", &n, &m)!=EOF)
{
if (!n&&!m) break;
for (int i = 0; i < n; i++)
{
int year, day, t;
char mon[10];
scanf("%s%d%d%d%d", &mon, &day, &year, &t, &a[i]);
time[i] = Time(year, MON(mon), day, t);
}
scanf("%d%d", &T, &S);
int l = 1, r = 0,idx=0;
ll ans = 0;
for (int i = 0; i < m; i++)
{
scanf("%d", &b[i]);
while (l <= r && (b[i] <= b[q[r]] + (i - q[r])*S)) r--;
q[++r] = i;
while (l <= r&&i - q[l]>T) l++;
while (idx < n&&i == time[idx]){
ans += a[idx]*(b[q[l]] + (i - q[l])*S);
idx++;
}
}
printf("%I64d\n", ans);
}
return 0;
}
评论