2011 Asia Fuzhou Regional Contest-1002 hdu4122

用RMQ选取指定区间内的最小值

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <memory.h>

using namespace std;

typedef long long ll;

ll num[] = {0,31,59,90,120,151,181,212,243,273,304,334,365};
ll t,s,n,m;
ll c[100050];
ll INF = 1 << 30;
ll d[100050][17];

class Node
{
      public :
      char mon[5];
      ll day,year,hour,r,sumhour,month;
      ll cost;
      public:
      bool getyear(int y)
      {
          if((y %4 == 0 && y % 100 != 0)||(y % 400 == 0))
              return true;
          else
              return false;
      }
      
      ll getyearsday()
      {
          ll sum = 0;
          for(int i = 2000;i < year;i++)
          {
              if(getyear(i)) sum += 366;
              else sum += 365;
          }
          return sum;
      }
      
      ll getmonth()
      {
          if(mon[0] == 'J')
          {
              if(mon[1] == 'a')return 1;
              else if(mon[1] == 'u')
              {
                  if(mon[2] == 'n')return 6;
                  else return 7;
              }
          }
          else if(mon[0] == 'F')return 2;
          else if(mon[0] == 'M')
          {
              if(mon[2] == 'r')return 3;
              else return 5;
          }
          else if(mon[0] == 'A')
          {
               if(mon[1] == 'p')return 4;
               else return 8;
          }
          else if(mon[0] == 'S') return 9;
          else if(mon[0] == 'O')return 10;
          else if(mon[0] == 'N')return 11;
          else if(mon[0] == 'D')return 12;
      }
      
      ll getday()
      {
          ll sum = getyearsday();
          if(!getyear(year))
          {
              sum += num[month -1];
              sum += day;
          }
          else
          {
              if(month <= 2)
              {
                  sum += num[month-1];
                  sum += day;
              }
              else
              {
                  sum += num[month -1]+1;
                  sum += day;
              }
          }
          return sum - 1;
      }
      
      ll gethour()
      {
           ll sum = getday() * 24;
           sum += hour;
           return sum;
      }
      
      void getcost()
      {
           if(sumhour - t > 1)
           {
               ll k = ll(log(t+1)/log(2));
               ll tmp = ll(pow(2.0,int(k)));
               cost = min(d[sumhour-t][k],d[sumhour - tmp + 1][k]);
           }
           else
           {
               ll k = ll(log(sumhour) / log(2));
               ll tmp = ll(pow(2.0,int(k)));
               cost = min(d[1][k],d[sumhour-tmp + 1][k]);
           }
           cost = (cost + sumhour * s)*r;
           return;
      }
      
      void init()
      {
           month = getmonth();
           sumhour = gethour()+1;
      }
}node[2505];

int main()
{
    INF = INF * INF;
    while(scanf("%I64d%I64d",&n,&m)!=EOF &&(n && m))
    {
        for(ll i = 1;i <= n;i++)
        {
            scanf("%s",&node[i].mon);
            scanf("%I64d%I64d%I64d%I64d",&node[i].day,&node[i].year,&node[i].hour,&node[i].r);
            node[i].init();
        }
        scanf("%I64d%I64d",&t,&s);
        ll ans = 0;
        for(ll i = 1;i <= m;i++)
        {
            scanf("%I64d",&c[i]);
            c[i] -= i*s;
        }
        memset(d,0,sizeof(d));
        for(ll i = 1;i <= m;i++)d[i][0] = c[i];
        for(ll i = 1;i <=ll(log(m)/log(2));i++)
        {
            for(ll j = 1;j <= m;j++)
            {
                d[j][i] = d[j][i-1];
                ll tmp = ll(pow(2.0,int(i-1)));
                if(j + tmp <= m && d[j+tmp][i-1] < d[j][i])
                    d[j][i] = d[j+tmp][i-1];
            }
        }
        for(ll i = 1;i <= n;i++)
        {
            node[i].getcost();
            ans += node[i].cost;
        }
        //cout << ans << endl;
        printf("%I64d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值