POJ 3171 区间最小花费覆盖 (DP+线段树

Cleaning Shifts

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 4245   Accepted: 1429

Description

Farmer John‘s cows, pampered since birth, have reached new heights of fastidiousness. They now require their barn to be immaculate. Farmer John, the most obliging of farmers, has no choice but hire some of the cows to clean the barn.

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

Line 1: Three space-separated integers: N, M, and E.

Lines 2..N+1: Line i+1 describes cow i‘s schedule with three space-separated integers: T1, T2, and S.

Output

Line 1: a single integer that is either the minimum total salary to get the barn cleaned or else -1 if it is impossible to clean the barn.

Sample Input

3 0 4
0 2 3
3 4 2
0 0 1

Sample Output

5

Hint

Explanation of the sample:

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

USACO 2005 December Silver

题意:给n个区间及其代价值,问要覆盖[M,E]区间至少要花费多少代价;

解法:这是一个dp问题,先列出方程。

F[i]表示取[0,i]这个区间的代价,初始化F[M-1]=0,答案就是F[E].

则方程为F[a[i].T2]=min(F[a[j].T2])+a[i].s (T1-1<=a[j].T2<T2),找min的过程用线段树实现。

将a[i]按T2从小到大排列,逐步更新最小值。

代码:

  1 #include"bits/stdc++.h"
  2
  3 #define ll long long
  4 #define vl vector<ll>
  5 #define ci(x) scanf("%d",&x)
  6 #define pi(x) printf("%d\n",x)
  7 #define pl(x) printf("%lld\n",x)
  8 #define rep(i, n) for(int i=0;i<n;i++)
  9 using namespace std;
 10 const int NN = 1e6 + 5;
 11 int n,s,t;
 12 struct P{int x,y,s;};
 13 P a[NN];
 14 bool cmp(P a,P b){
 15     return a.y<b.y;
 16 }
 17 const ll INF = 0x3fffffffffffffff;
 18 struct SegMin {
 19     int N;
 20     vl is;vl mul;vl add;
 21     ll init;
 22     ll merge(ll a, ll b) {
 23         return min(a, b);
 24     }
 25     void push(int o, int L, int R, ll m, ll a) {
 26         is[o] = is[o] * m + a;
 27         mul[o] = mul[o] * m;
 28         add[o] = add[o] * m + a;
 29     }
 30
 31     SegMin(int n, ll init=INF) {
 32         N = 1;
 33         while (N < n) N *= 2;
 34         this->init = init;
 35         is = vl(N * 4, init);
 36         mul = vl(N * 4, 1);
 37         add = vl(N * 4);
 38     }
 39
 40     SegMin(vl a, ll init=INF) {
 41         int n = a.size();
 42         N = 1;
 43         while (N < n) N *= 2;
 44         this->init = init;
 45         is = vl(N * 2);
 46         mul = vl(N * 2, 1);
 47         add = vl(N * 2);
 48         copy(a.begin(), a.end(), is.begin() + N);
 49         for (int i = N - 1; i > 0; i--) {
 50             is[i] = merge(is[i << 1], is[i << 1 | 1]);
 51         }
 52     }
 53
 54     void update(int l, int r, ll m, ll a) {
 55         if (l < r) update(1, 0, N, l, r, m, a);
 56     }
 57
 58     void update(int o, int L, int R, int l, int r, ll m, ll a) {
 59         if (l <= L && R <= r) {
 60             push(o, L, R, m, a);
 61         } else {
 62             int M = (L + R) >> 1;
 63             push(o, L, M, R);
 64             if (l < M) update(o << 1, L, M, l, r, m, a);
 65             if (r > M) update(o << 1 | 1, M, R, l, r, m, a);
 66             is[o] = merge(is[o << 1], is[o << 1 | 1]);
 67         }
 68     }
 69
 70     void push(int o, int L, int M, int R) {
 71         if (mul[o] != 1 || add[o] != 0) {
 72             push(o << 1, L, M, mul[o], add[o]);
 73             push(o << 1 | 1, M, R, mul[o], add[o]);
 74             mul[o] = 1;
 75             add[o] = 0;
 76         }
 77     }
 78
 79     ll query(int l, int r) {
 80         if (l < r) return query(1, 0, N, l, r);
 81         return init;
 82     }
 83
 84     ll query(int o, int L, int R, int l, int r) {
 85         if (l <= L && R <= r) {
 86             return is[o];
 87         } else {
 88             int M = (L + R) >> 1;
 89             push(o, L, M, R);
 90             ll res = init;
 91             if (l < M) res = merge(res, query(o << 1, L, M, l, r));
 92             if (r > M) res = merge(res, query(o << 1 | 1, M, R, l, r));
 93             is[o] = merge(is[o << 1], is[o << 1 | 1]);
 94             return res;
 95         }
 96     }
 97 };
 98
 99 int main(){
100     ci(n),ci(s),ci(t);//s从1开始
101     s++,t++;
102     int ma=0;
103     for(int i=0;i<n;i++) ci(a[i].x),ci(a[i].y),ci(a[i].s);
104     for(int i=0;i<n;i++) a[i].x++,a[i].y++,ma=max(ma,a[i].y);
105     sort(a,a+n,cmp);
106     SegMin seg(ma+1);
107     seg.update(0,ma+1,0,INF);
108     seg.update(0,s,0,0);
109
110     for(int i=0;i<n;i++){
111         if(a[i].y<s) continue;
112         int L=a[i].x-1,R=a[i].y;
113         ll res=seg.query(L,R)+a[i].s;
114         res=min(seg.query(R,R+1),res);//与前面的最小值取min
115         seg.update(R,R+1,0,res);
116     }
117     ll ans=seg.query(t,ma+1);
118     if(ans>=INF) puts("-1");//未覆盖到
119     else pl(ans);
120     return 0;
121 }

原文地址:https://www.cnblogs.com/mj-liylho/p/9502012.html

时间: 2024-10-08 23:03:38

POJ 3171 区间最小花费覆盖 (DP+线段树的相关文章

POJ - 2528 Mayor&#39;s posters (离散化+线段树区间修改)

https://cn.vjudge.net/problem/POJ-2528 题意 给定一些海报,可能相互重叠,告诉你每个海报的宽度(高度都一样的)和先后叠放顺序,问没有被完全盖住的有多少张? 分析 海报最多10000张,但是墙有10000000块瓷砖长,海报不会落在瓷砖中间. 如果直接建树,就算不TLE,也会MLE.即单位区间长度太多. 其实10000张海报,有20000个点,最多有19999个区间.对各个区间编号,就是离散化.然后建树. 可以直接进行区间修改,最后再统计. 这里采用比较巧妙的

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac

POJ 1422 DAG最小路径覆盖

求无向图中能覆盖每个点的最小覆盖数 单独的点也算一条路径 这个还是可以扯到最大匹配数来,原因跟上面的最大独立集一样,如果某个二分图(注意不是DAG上的)的边是最大匹配边,那说明只要取两个端点只要一条边即可. 故最小覆盖数还是 顶点数-最大匹配数 根据DAG建图的时候,就是DAG有边就给对应的端点建边 #include <iostream> #include <cstdio> #include <cstring> using namespace std; int d[15

POJ 3468-A Simple Problem with Integers(线段树:成段更新,区间求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 62228   Accepted: 19058 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

POJ 2528 Mayor&#39;s posters (离散化+线段树区间更新)

Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for

POJ A Simple Problem with Integers 【线段树,区间更新】

题意:你有N个整数,A1,A2,-,一个.你需要处理两种类型的操作.一种类型的操作是添加了一些给定的数字,每个数字在一个给定的时间间隔.另一种是在给定的时间间隔要求数量的总和. 难点:主要是lazy标记,不好弄懂, 其实lazy标记就是当前改变的值不全部更新,等到用的时候再更新,这样就节省了好多时间. 题目链接:http://poj.org/problem?id=3468 代码: #include<stdio.h> #include<string.h> #define MAXN 1

HDU 3698 DP+线段树

给出N*M矩阵.每一个点建立灯塔有花费.每一个点的灯塔有连接范围,求每一行都建立一个灯塔的最小花费,要求每相邻两行的灯塔能够互相连接.满足 |j-k|≤f(i,j)+f(i+1,k) DP思路,dp[i][j]=在第i行的j位置放置灯塔的最小花费.dp[i][j]=Min(dp[i-1][k]+a[i][j]),同一时候更新当前点能够覆盖该行的全部位置的最小值 要求上个区间的最小值,用线段树优化,否则超时 滚动数组,否则超内存 #include "stdio.h" #include &

poj 2886 Who Gets the Most Candies?(线段树+约瑟夫环+反素数)

Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 9934   Accepted: 3050 Case Time Limit: 2000MS Description N children are sitting in a circle to play a game. The children are numbered from 1 to N in clockwise o

poj 2528 Mayor&#39;s posters【离散化+线段树】

题目:poj 2528 Mayor's posters 题意:给一个长度非常长的墙上贴长度为ai的海报,由于有的会覆盖掉,求最后能看见的海报个数. 分析:题目和POJ2777 一模一样,方法也一样,只不过这个要离散化,其次要数组开大一点.至少2倍. 离散化的时候用了C++的 pair 类,还是比较好用的. 代码: #include <iostream> #include <algorithm> #include <utility> #include <cstrin