HDU 4122 单调队列

转载自:http://blog.csdn.net/lvshubao1314/article/details/46910271

DES :给出n个订单和m是商店的开放时间。然后n行给出n个订单的信息。然后给出t和s。表示一个月饼的保质期和保存一天的成本。最后m行,给出每个时刻做月饼的成本。问。完成订单的最少的成本是多少。

思路就是用单调队列保存每个点之前的可以为这个点做月饼的点。刚学了单调队列。在保存下标然后找到值哪里还是有一些混乱。

第一次错了。闰年是366天。搞混了。T_T。不过时间方面的计算还是。。有点蠢。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6
 7 int time[2600];
 8 int cost[100010];
 9 int order[2600];
10 int inque[100010];
11
12 char mon[13][5] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
13
14 bool isleap(int year) {
15      if (year%400 == 0)
16         return true;
17      else if (year%100 && (year%4==0))
18         return true;
19      return false;
20 }
21
22 int year_Day(int year) {
23     int ans = 0;
24     for (int i=2000; i<year; ++i) {
25         if (isleap(i)) ans += 366;
26         else ans += 365;
27     }
28     return ans;
29 }
30
31 int mon_Day(bool leap, int mon) {
32    switch (mon) {
33        case 1: return 0;
34        case 2: return 31;
35        case 3: return leap ? 60 : 59;
36        case 4: return leap ? 91 : 90;
37        case 5: return leap ? 121 : 120;
38        case 6: return leap ? 152 : 151;
39        case 7: return leap ? 182 : 181;
40        case 8: return leap ? 213 : 212;
41        case 9: return leap ? 244 : 243;
42        case 10: return leap ? 274 : 273;
43        case 11: return leap ? 305 : 304;
44        case 12: return leap ? 335 : 334;
45    }
46 }
47
48 int get_mnum(char monn[]) {
49     for (int i=0; i<12; ++i) {
50         if (strcmp(monn, mon[i]) == 0)
51             return i+1;
52     }
53 }
54
55 int getTime(char mon[], int dat, int year, int h) {
56     bool leap = isleap(year);
57     int ans = year_Day(year);
58     int m = get_mnum(mon);
59     ans += mon_Day(leap, m);
60     ans += dat-1;
61     ans *= 24;
62     ans += h;
63     return ans;
64 }
65
66 int main() {
67     int n, m;
68     int t, s;
69     char monn[5];
70     int dat, year, h, r;
71     while(cin >> n >> m) {
72         if (n == 0 && m == 0) break;
73         for (int i=0; i<n; ++i) {
74             cin >> monn >> dat >> year >> h >> r;
75             time[i] = getTime(monn, dat, year, h);
76             //cout << time[i] << endl;
77             order[i] = r;
78         }
79         cin >> t >> s;
80         int tnum = 0;
81         int ans = 0;
82         int head=0, tail=0;
83         for (int i=0; i<m; ++i) {
84             cin >> cost[i];
85             while(head < tail && cost[inque[tail-1]]+s*(i-inque[tail-1]) > cost[i])
86                 tail--;
87             inque[tail++] = i;
88             while(i == time[tnum]) {
89               while(head<tail && i-inque[head]>t)
90                   head++;
91               ans += order[tnum]*(cost[inque[head]]+s*(i-inque[head]));
92               tnum++;
93            }
94         }
95         cout << ans << endl;
96     }
97     return 0;
98 }

时间: 2024-10-29 04:04:10

HDU 4122 单调队列的相关文章

HDU 3507 单调队列 斜率优化

斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方法来做,但是该题要求的是区间和的平方,于是要转换单调的计算方法为斜率,也就是凸线. 其他就是最基本的单调DP /** @Date : 2017-09-04 15:39:05 * @FileName: HDU 3507 单调队列 斜率优化 DP.cpp * @Platform: Windows * @

HDU 3530 单调队列

Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3995    Accepted Submission(s): 1308 Problem Description There is a sequence of integers. Your task is to find the longest subsequenc

hdu 3415 单调队列

Max Sum of Max-K-sub-sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5690    Accepted Submission(s): 2059 Problem Description Given a circle sequence A[1],A[2],A[3]......A[n]. Circle s

hdu 3401 单调队列优化+dp

http://acm.hdu.edu.cn/showproblem.php?pid=3401 Trade Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5188    Accepted Submission(s): 1776 Problem Description Recently, lxhgww is addicted to stoc

hdu 3401(单调队列优化dp)

注意:这题题意是有操作的天数相隔要大于w 然后列出状态转移方程就可以发现,可以用优点队列优化啦. 构造状态dp[i][j]表示第i 天拥有 j只股票的时候,赚了多少钱 状态转移有: 1.从前一天不买不卖: dp[i][j]=max(dp[i-1][j],dp[i][j]) 2.从前i-W-1天买进一些股: dp[i][j]=max(dp[i-W-1][k]-(j-k)*AP[i],dp[i][j]) 3.从i-W-1天卖掉一些股: dp[i][j]=max(dp[i-W-1][k]+(k-j)*

hdu 4193 单调队列

题意是给你n个数   组成的环   求以一个数开头 的数列所有前缀都为非负数的数列的个数: 思路:  先扩展成2*n的数列 然后求出sum[i]表示前i项的和     对每个i>.=n结尾的数列  只要单调队列里的最小值大于等于sum[i-n]就满足情况(想想为什么)   对于单调队列  只要维护长度大于等于n   递增的就行: #include<stdio.h> #include<string.h> #include<iostream> using namesp

hdu 4374 单调队列

求最大不超过k的连续子序列的和   单调队列 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; int num[201000],id[201000],sum[201000]; int main() { int n,m,i,j,T; scanf("%d",&T); while(T--) { scanf("%d%d",&am

hdu 3530 单调队列水题

给你一个数列找到最长的子序列   中的最大值减最小值值m   k之间 建立两个单调队列   一个递增    一个递减    当两个队首满足情况是就进行比较 找到最大值 当不满足是旧的移动队首      怎样移??? 移动队首id较小的一个 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; int max(int a,int b) { return a>b?a:b

hdu 5289 单调队列

#include <iostream> #include <cstdio> #include <queue> #include <deque> using namespace std; typedef pair<int, int> P; #define maxn 100000 + 10 deque<long long> Q1; //up deque<long long> Q2; //down int n, k; long