hdu 单调队列
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4122
代码:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<map> #include<string> using namespace std; const int maxn = 100500; struct Node { int id,val; }; int order[2555]; long long R[2555]; int S,T,N,M; struct Myqueue { Node Q[maxn]; int head,tail; void init() { head = tail = 0; } void push(int id,int val) { while(head < tail && Q[tail-1].val+S*(id-Q[tail-1].id) >= val) tail--; Q[tail].val = val; Q[tail++].id = id; } void pop(int id) { while(head < tail && Q[head].id < id - T) //单调区间的最小值。 head++; } Node getfront() { return Q[head]; } }solver; map<string,int> mymap; void init() { mymap["Jan"] = 1; mymap["Feb"] = 2; mymap["Mar"] = 3; mymap["Apr"] = 4; mymap["May"] = 5; mymap["Jun"] = 6; mymap["Jul"] = 7; mymap["Aug"] = 8; mymap["Sep"] = 9; mymap["Oct"] = 10; mymap["Nov"] = 11; mymap["Dec"] = 12; } int mou[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; void GetOrder() { string s; int date,year,H; for(int i=1; i<=N; i++) { cin>>s; scanf("%d %d %d %I64d",&date,&year,&H,&R[i]); int mouth = mymap[s]; year -= 2000; order[i] = (365*4+1)*(year/4); year = year%4; if(year == 0) { for(int j=1; j<mouth; j++) { order[i] += mou[j]; if(j == 2) order[i] += 1; } } else { order[i] += 366 + (year-1)*365; for(int j=1; j<mouth; j++) order[i] += mou[j]; } order[i] += date - 1; order[i] = order[i]*24 + H + 1; } } int main() { //freopen("E:\\acm\\input.txt","r",stdin); init(); while(cin>>N>>M && N+M) { GetOrder(); scanf("%d %d",&T,&S); solver.init(); int cnt = 1; long long ans = 0; for(int i=1; i<=M; i++) { int cost; scanf("%d",&cost); solver.push(i,cost); solver.pop(i); //先去掉过期的 Node cur = solver.getfront(); while(order[cnt] == i && cnt <= N) //cnt的上限,和while循环,考虑了,为啥不加。 { ans += (cur.val + (i-cur.id)*S ) * R[cnt]; //乘法溢出问题 cnt ++; } } printf("%I64d\n",ans); } }