题意比较简单,状态转移方程也比较容易得出:
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: [email protected] 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 long 20 #define LLU unsigned long long 21 22 using namespace std; 23 24 struct node 25 { 26 int s,t,p; 27 bool operator<(const node &c) const 28 { 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 else 49 { 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 }