SPOJ130_Rent your airplane and make money_单调队列DP实现

来源:互联网 发布:nodejs读取json文件 编辑:程序博客网 时间:2024/05/22 06:36

题意比较简单,状态转移方程也比较容易得出:

f[i]=max{ f [ j ] }+p[i],(j的结束时间在i开始时间之前)

若i开始之前没有结束的j,则f[i]=p[i];

因数据量太大(n<=10000)因此必须优化,这里使用单调队列降低时间复杂度

首先按开始时间排序,队列里存的是编号,队列要求是开始时间严格递增,f[i]利润值严格递增,每次只需维护单调队列,就能将dp部分降到O(n),因插入队列是用到二分查找,所以总的时间为O(nlogn)

维护单调队列的思路:求f[i]时,从队头开始遍历,找到在i开始时间之前最后结束的j,然后将j之前的全部出队,插入时,首先根据i的结束时间二分查找出i可能插入的位置x,然后看该位置之后的f[x]小于等于f[i]的编号x全部删除,然后若i可以放在此处(两种情况:1.空队时,2.f[i]比f[x]小比f[x-1]大时,刚开始这个地方没处理好,WA了n次!!!),则将i插入单调队列。最后求出最大的f[i]即可。

 1 /************************************************************************* 2     > File Name: A.cpp 3     > Author: Chierush 4     > Mail: qinxiaojie1@gmail.com  5     > Created Time: 2013年07月26日 星期五 10时52分21秒 6  ************************************************************************/ 7  8 #include <iostream> 9 #include <cstring>10 #include <cstdlib>11 #include <set>12 #include <cstdio>13 #include <string>14 #include <vector>15 #include <map>16 #include <cmath>17 #include <algorithm>18 19 #define LL long long20 #define LLU unsigned long long21 22 using namespace std;23 24 struct node25 {26     int s,t,p;27     bool operator<(const node &c) const28     {29         if (s!=c.s) return s<c.s;30         return t<c.t;31     }32 };33 34 node a[10005];35 vector<int>q;36 int f[10005];37 38 int find(int x)39 {40     if (a[q[q.size()-1]].s+a[q[q.size()-1]].t<x) return q.size();41     int l=0,r=q.size(),m;42     while (l<r)43     {44         if (l+1==r) return l;45         m=(l+r)/2;46         if (a[q[m]].s+a[q[m]].t<x) l=m;47         else if (a[q[m]].s+a[q[m]].t==x) return m;48         else49         {50             if (m)51             {52                 if (a[q[m-1]].s+a[q[m-1]].t>=x) r=m;53                 else return m;54             }55             else return m;56         }57     }58 }59 60 int main()61 {62     int T,n;63     scanf("%d",&T);64     while (T--)65     {66         scanf("%d",&n);67         for (int i=0;i<n;++i)68             scanf("%d%d%d",&a[i].s,&a[i].t,&a[i].p);69         sort(a,a+n);70         int ans;71         f[0]=ans=a[0].p;72         q.clear();73         q.push_back(0);74         for (int i=1;i<n;++i)75         {76             while (q.size()>1 && a[q[1]].s+a[q[1]].t<=a[i].s) q.erase(q.begin());77             if (a[q[0]].s+a[q[0]].t<=a[i].s) f[i]=a[i].p+f[q[0]];78             else f[i]=a[i].p;79             int x=find(a[i].s+a[i].t);80             while (q.size()>x && f[i]>=f[q[x]]) q.erase(q.begin()+x); 81             if (!q.size() || (q.size()==x && f[i]>f[q[x-1]]) || (q.size()>x && a[q[x]].s+a[q[x]].t>a[i].s+a[i].t && (!x || f[q[x-1]]<f[i]))) q.insert(q.begin()+x,i);82             ans=max(ans,f[i]);83         }84         printf("%d\n",ans);85     }86     return 0;87 }
View Code

<script type="text/javascript"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 1岁拉稀水怎么办 新生儿婴儿呕奶怎么办 儿童肚子着凉拉肚子怎么办 七个月宝宝拉肚子怎么办 小孩大便果冻状怎么办 五个月婴儿拉稀怎么办 孩子老是着凉怎么办呢 五个月孩子拉肚子怎么办 肚子着凉了拉稀怎么办 小孩子着凉吐奶怎么办 儿童大便有粘液怎么办 宝宝拉鼻涕屎怎么办 婴儿拉白色粘液怎么办 宝宝不肯吃鱼肝油怎么办 婴儿不肯吃鱼肝油怎么办 宝宝吃鱼肝油吐怎么办 五个月婴儿夏天怎么办 厌奶期宝宝瘦了怎么办 二个月的宝宝不喝夜奶怎么办 婴儿不喝奶粉怎么办 小孩整天不吃饭怎么办 婴儿不吃不喝怎么办 断奶后不吃奶瓶怎么办 小孩早上不吃饭怎么办 新生儿不认乳头怎么办 宝宝不吸奶嘴怎么办 孩子不会吸奶瓶怎么办 宝宝突然不吃奶瓶怎么办 换了奶瓶不喝奶怎么办 新生儿不喝奶粉怎么办 7个月小婴儿磨牙怎么办 宝宝出生四天不喝母乳怎么办 我的奶水不足怎么办 乳牙长得不整齐怎么办 新生儿只吃奶粉怎么办 小孩不肯吸母乳怎么办 三个月宝宝不吃奶粉怎么办 宝宝不爱喝水怎么办 崔玉涛 小孩身体铅过高怎么办 疫苗引起的发烧怎么办 婴儿不吃米糊怎么办