hdu4122(模拟+单调队列+处理方式)

模拟题就是有坑!!!!见代码注释

题意:Alice开了家月饼店,现有2500笔订单,订单包括某小时(2000年1月1日0点算第1个小时的开始)和需要的月饼数量。然后给你前100000小时的信息,包括第i个小时做1个饼的花费cost[i]。然后给你月饼的保质期T(说明订单i只能买[order[i].hour-T , order[i].hour ]这个区间生产的饼)和保存1小时的花费S,让你求最小的花费满足所有订单。

分析:首先要把订单的时间转化成自2000年1月1日0点开始的第几小时,由于最多100000小时,所以最大到2012年的样子。然后维护一个最小值的单调队列。

 

//#pragma comment(linker, "/STACK:102400000")
#include<cstdlib>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<vector>
#define tree int o,int l,int r
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lo o<<1
#define ro o<<1|1
#define pb push_back
#define mp make_pair
#define ULL unsigned long long
#define LL long long
#define inf 0x7fffffff
#define eps 1e-7
#define N 2509
#define M 100009
using namespace std;
int m,n,T,t,s;
int ti[N],num[N];
LL ans;
int q[M],c[M];
char tr[13][10]= { "","Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int mon[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
int get(int k)
{
    char str[10];
    int d,y,h,m;
    scanf("%s%d%d%d%d",str,&d,&y,&h,&num[k]);
    for (int i=1; i<13; ++i )
        if(strcmp(tr[i],str)==0)
        {
            m=i;
            break;
        }
    int ans=0;
    for(int i=2000; i<y; i++)
    {
        if((i%400==0)||(i%100!=0&&i%4==0))
            ans+=366;
        else
            ans+=365;
    }
    if((y%400==0)||(y%100!=0&&y%4==0))
        mon[2]=29;
    else
        mon[2]=28;
    for(int i=1; i<m; i++)
        ans+=mon[i];
    ans+=d-1;
    ans*=24;
    ans+=h+1;
    return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("ex.in","r",stdin);
#endif
    while(scanf("%d%d%*c",&n,&m)==2)
    {
        if(!n&&!m)return 0;
        for (int i=0; i<n; ++i )
        {
            ti[i]=get(i);
        }
        scanf("%d%d",&t,&s);
        int l=0,r=0,cnt=0;
        ans=0;
        for (int i=1; i<=max(m,ti[n-1]); ++i )//超出m的订单也是可以的
        {
            if(i<=m)
            {
                scanf("%d",&c[i]);
                while(l<r&&((LL)i-q[r-1])*s+c[q[r-1]]>=c[i])
                    r--;
                q[r++]=i;
            }
            while(l<r&&i-q[l]>t)l++;
            while(i==ti[cnt])//题目中说是升序,但是有相等的,(WA)
            {
                ans+=((LL)(i-q[l])*s+c[q[l]])*num[cnt];
                cnt++;
            }
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

 

 

posted @ 2013-10-21 11:11  baoff  阅读(258)  评论(0编辑  收藏  举报