HDU 4122 线段树+时间处理

勉强归类到线段树里面吧


先求出每个订单对应的时间点存入time

data[k].min 存储当前位置做月饼保存到最后一个订单的花费

然后线段树从第n个订单到第1个订单, 搜区间 【 time[n]-t  ,time[n] 】    即可



#include "stdio.h"
#include "string.h"
#include "math.h"
#include "stdlib.h"


struct comp
{
    int l,r,mid;
    __int64 min;
} data[500010];

int dayy[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int count[100010];
int time[100010];
__int64 s,a[100010];
int t,n;
int judge(int w)
{
    if ((w%4==0 && w%100!=0) || w%400==0) return 1;
    else return 0;
}
__int64 minn(__int64 x,__int64 y)
{
    if (x<y) return x;
    else return y;
}

int find_time(char str[10],int day,int year,int hour)
{
    int ans,i,month;
    ans=0;
    for (i=2000;i<year;i++)
        if (judge(i)==1) ans+=366*24;
        else ans+=365*24;

    if (strcmp(str,"Jan")==0) month=1;
    if (strcmp(str,"Feb")==0) month=2;
    if (strcmp(str,"Mar")==0) month=3;
    if (strcmp(str,"Apr")==0) month=4;
    if (strcmp(str,"May")==0) month=5;
    if (strcmp(str,"Jun")==0) month=6;
    if (strcmp(str,"Jul")==0) month=7;
    if (strcmp(str,"Aug")==0) month=8;
    if (strcmp(str,"Sep")==0) month=9;
    if (strcmp(str,"Oct")==0) month=10;
    if (strcmp(str,"Nov")==0) month=11;
    if (strcmp(str,"Dec")==0) month=12;

    for (i=1;i<month;i++)
        if (i==2 && judge(year)==1) ans+=29*24;
        else ans+=dayy[i]*24;

    ans+=(day-1)*24;
    ans+=hour;

    return ans;
}

void build(int l,int r,int k)
{
    data[k].l=l;
    data[k].r=r;
    data[k].mid=(l+r)/2;
    
    if (l==r)
    {
        data[k].min=a[l]+s*(time[n]-l);
        return ;
    }

    build(l,data[k].mid,k*2);
    build(data[k].mid+1,r,k*2+1);

    if (data[k*2].min<data[k*2+1].min) data[k].min=data[k*2].min;
    else data[k].min=data[k*2+1].min;
}

__int64 search(int l,int r,int k)
{
    if (data[k].l==l && data[k].r==r) 
        return data[k].min;

    if (r<=data[k].mid) return search(l,r,k*2);
    else 
        if (l>data[k].mid) return search(l,r,k*2+1);
        else 
            return minn(search(l,data[k].mid,k*2),search(data[k].mid+1,r,k*2+1));
}



int main()
{
    __int64 ans;
    int m,i;
    int day,year,hour;
    __int64 min,ll;
    char str[20];
    

    while (scanf("%d%d",&n,&m)!=EOF)
    {
        if (n==0 && m==0) break;

        for (i=1;i<=n;i++)
        {
            scanf("%s%d%d%d%d",str,&day,&year,&hour,&count[i]);
            time[i]=find_time(str,day,year,hour);
        }

        scanf("%d%I64d",&t,&s);

        for (i=0;i<m;i++)
            scanf("%I64d",&a[i]);

        build(0,m-1,1);

        ans=0;
        for (i=n;i>=1;i--)
        {
            ll=time[i]-t;
            if (ll<0) ll=0;

            min=search(ll,time[i],1);

            ll=(time[n]-time[i])*s*count[i];
            ans+=(min*count[i])-ll;
        }

        printf("%I64d\n",ans);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值