hdu 4122 (线段树)

题意:月饼商店从2000年1月1日0时开始开m个小时,只能在整点的时候才能做月饼,给出每个时间点做一个月饼的费用,做月饼的时间不计,有n个订单,取货的日期和数量,商店有冷藏库,容量无限大,月饼的冷藏时间有限,冷藏是要花钱的,求出这n个订单总共最少得花多少钱。

思路:对于每个订单ti都是在ti-t—ti时间段内找出做月饼花费最小时间点,可以先求出任意时间点做月饼满足最后一个订单的费用(不考虑冷藏时限),然后用线段树处理区间最小值,然后对于每个订单找出ti-t—ti区间的最小值,然后要减去该订单的时间到最后订单时间的冷藏费用。ti-t可能小于0,ti可能大于m。





#include<stdio.h>
#include<string.h>
const int N=100100;
int time[N],n,aa[N];
char ss[15][10]= {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
int days[15]= {31,28,31,30,31,30,31,31,30,31,30,31};
struct date
{
    int year,month,day,hour,cont;
}mark[N];
int min(int a,int b)
{
    if(a>b)return b;
    return a;
}
int leap(int year)
{
    return (year%4==0&&year%100!=0)||year%400==0;
}
int tianshu(date a)//求天数
{
    int ret=a.year*365+(a.year-1)/4-(a.year-1)/100+(a.year-1)/400,i;
    days[1]+=leap(a.year);
    for(i=0; i<a.month-1; ret+=days[i++]);
    days[1]=28;
    return ret+a.day;
}
int hanshu(date a,date b)//求小时
{
    int rest=tianshu(a)-tianshu(b);
    rest*=24;
    if(b.hour<a.hour)
        rest+=(a.hour-b.hour);
    else rest-=(b.hour-a.hour);
    return rest+b.hour;
}
void Time()
{
    int i,j;
    char str[10];
    for(i=1; i<=n; i++)
    {
        scanf("%s%d%d%d%d",str,&mark[i].day,&mark[i].year,&mark[i].hour,&mark[i].cont);
        for(j=0;j<12; j++)
        {
            if(strcmp(str,ss[j])==0)
            {
                mark[i].month=j+1;
                break;
            }
        }
    }
    mark[0].year=2000; mark[0].month=1; mark[0].day=1;mark[0].hour=0;
    for(i=1; i<=n; i++)
        time[i]=hanshu(mark[i],mark[0]);//订单的时间
}
struct Tree
{
    int L,R,mw;
}T[N*5];
void buildTree(int L,int R,int id)
{
    T[id].L=L;T[id].R=R;
    if(L==R)
    {
        T[id].mw=aa[L];
        return ;
    }
    int mid=(L+R)>>1,li=id<<1,ri=li|1;
    buildTree(L,mid,li);
    buildTree(mid+1,R,ri);
    T[id].mw=min(T[li].mw,T[ri].mw);
}
int find(int L,int R,int id)
{
    if(T[id].L==L&&T[id].R==R)
       return T[id].mw;
    int mid=(T[id].L+T[id].R)>>1,li=id<<1,ri=li|1;
    if(R<=mid)
        return find(L,R,li);
    else if(L>mid)
        return find(L,R,ri);
    else
        return min(find(L,mid,li),find(mid+1,R,ri));
}
int main()
{

	int m,i,tt,s;
	__int64 temp,ans;
	while (scanf("%d%d",&n,&m)!=EOF)
	{
		if (n==0 && m==0) break;
        memset(time,0,sizeof(time));
        Time();
		scanf("%d%d",&tt,&s);
		for(i=0;i<m;i++)
		{
			scanf("%d",&aa[i]);
			if(i<=time[n])
			aa[i]+=((time[n]-i)*s);
		}
		buildTree(0,time[n],1);
		ans=0;
		for(i=1;i<=n;i++)
		{
			if(time[i]-tt<0)
				temp=find(0,min(m-1,time[i]),1);
			else 
				temp=find(time[i]-tt,min(m-1,time[i]),1);
			temp-=((time[n]-time[i])*s);
			ans+=(temp*mark[i].cont);
		}
		printf("%I64d\n",ans);
	}
	return 0;
}





点赞