Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 4721 | Accepted: 1593 |
Description
Farmer John has N (1 <= N <= 10,000) cows who are willing to do some cleaning. Because dust falls continuously, the cows require that the farm be continuously cleaned during the workday, which runs from second number M to second number E during the day (0 <= M <= E <= 86,399). Note that the total number of seconds during which cleaning is to take place is E-M+1. During any given second M..E, at least one cow must be cleaning.
Each cow has submitted a job application indicating her willingness to work during a certain interval T1..T2 (where M <= T1 <= T2 <= E) for a certain salary of S (where 0 <= S <= 500,000). Note that a cow who indicated the interval 10..20 would work for 11 seconds, not 10. Farmer John must either accept or reject each individual application; he may NOT ask a cow to work only a fraction of the time it indicated and receive a corresponding fraction of the salary.
Find a schedule in which every second of the workday is covered by at least one cow and which minimizes the total salary that goes to the cows.
Input
Lines 2..N+1: Line i+1 describes cow i's schedule with three space-separated integers: T1, T2, and S.
Output
Sample Input
3 0 4
0 2 3
3 4 2
0 0 1
Sample Output
5
Hint
FJ has three cows, and the barn needs to be cleaned from second 0 to second 4. The first cow is willing to work during seconds 0, 1, and 2 for a total salary of 3, etc.
Farmer John can hire the first two cows.
Source
题意就是给你一些小区间,用小区间去覆盖大区间,求最小花费。
数据结构优化动态规划,这是一个区间最值问题。
将小区间按照右端点排序,然后遍历小区间,每次都找小区间左边到小区间右边的最小值,然后最小值更新,只单点更新右端点就可以(降维)。
一开始想的区间更新,按照贴纸,直接成段更新,后来发现思路是错的,因为区间更新会覆盖掉其他的值。所以要用单点更新。
线段树每个点表示到当前区间段的最优解,直接初始化为inf,然后M-1更新为0,就可以。
每次都是查找a[i].l-1到a[i].r的最小值(因为是片段,所以从a[i].l-1开始查找),然后更新a[i].r。直接线段树维护区间的最小值。
动态规划方程式就是dp[i]=min(query(a[i].l-1,a[i].r))+a[i].val;表示覆盖到a[i].r的最小花费。因为小区间不能间断,所以要这样查询更新。
因为直接遍历的,所以dp[i]这个方程式都可以省略,直接查值然后更新值到线段树里就可以了。
因为每次都是从a[i].l-1开始,而且题目数据最小可能为0,所以直接端点都+2,这样,最小的值查找的时候也是从1开始的。
写题的时候,不能乱秀,容易把自己秀死。。。
自己写的时候,特判了一下如果最左端点和最端点不能包含大区间,直接-1输出。结果忘了我是按照右端点排序的,右边是对的,左边的不一定是对的。。。
最后直接查询大区间右端点和小区间最右端点。判断一下值就可以了。
如果ans<inf说明都能覆盖到,如果有inf说明有的地方没被覆盖到。
代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<bitset>
6 #include<cassert>
7 #include<cctype>
8 #include<cmath>
9 #include<cstdlib>
10 #include<ctime>
11 #include<deque>
12 #include<iomanip>
13 #include<list>
14 #include<map>
15 #include<queue>
16 #include<set>
17 #include<stack>
18 #include<vector>
19 using namespace std;
20 typedef long long ll;
21 typedef long double ld;
22 typedef pair<int,int> pii;
23
24 const double PI=acos(-1.0);
25 const double eps=1e-6;
26 const ll mod=1e9+7;
27 const ll inf=1e18;
28 const int maxn=1e5+10;
29 const int maxm=100+10;
30 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
31 #define lson l,m,rt<<1
32 #define rson m+1,r,rt<<1|1
33
34 struct node{
35 int l,r;
36 ll val;
37
38 friend bool operator<(node a,node b){
39 if(a.r==b.r) return a.l<b.l;
40 return a.r<b.r;
41 }
42
43 }a[maxn];
44
45 ll tree[maxn<<2];
46
47 void pushup(int rt)
48 {
49 tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
50 }
51
52 void build(int l,int r,int rt)
53 {
54 if(l==r){
55 tree[rt]=inf;
56 return ;
57 }
58
59 int m=(l+r)>>1;
60 build(lson);
61 build(rson);
62 pushup(rt);
63 }
64
65 void update(int pos,ll c,int l,int r,int rt)
66 {
67 if(l==r){
68 tree[rt]=min(tree[rt],c);
69 return ;
70 }
71
72 int m=(l+r)>>1;
73 if(pos<=m) update(pos,c,lson);
74 if(pos> m) update(pos,c,rson);
75 pushup(rt);
76 }
77
78 ll query(int L,int R,int l,int r,int rt)
79 {
80 if(L<=l&&r<=R){
81 return tree[rt];
82 }
83
84 int m=(l+r)>>1;
85 ll ret=inf;
86 if(L<=m) ret=min(ret,query(L,R,lson));
87 if(R> m) ret=min(ret,query(L,R,rson));
88 return ret;
89 }
90
91 int main()
92 {
93 int n,M,E;
94 cin>>n>>M>>E;
95 for(int i=1;i<=n;i++){
96 cin>>a[i].l>>a[i].r>>a[i].val;
97 a[i].l+=2,a[i].r+=2;
98 }
99 M+=2,E+=2;
100 sort(a+1,a+1+n);
101 build(1,maxn,1);
102 update(M-1,0,1,maxn,1);
103 for(int i=1;i<=n;i++){
104 ll cnt=query(a[i].l-1,a[i].r,1,maxn,1);
105 cnt+=a[i].val;
106 update(a[i].r,cnt,1,maxn,1);
107 }
108 ll ans=query(E,a[n].r,1,maxn,1);
109 if(ans<inf) cout<<ans<<endl;
110 else cout<<"-1"<<endl;
111 }
OK了。
来源:oschina
链接:https://my.oschina.net/u/4385788/blog/3587973