题目链接 2017 CCPC Harbin Problem K
题意 给定若干物品,每个物品可以覆盖一个区间。现在要覆盖区间$[1, t]$。
求选出来的物品的$\frac{∑a_{i}}{∑b_{i}}$的最小值。
首先二分答案,那么每个物品的权值就变成了$x * b_{i} - a_{i}$
在判断的时候先把那些权值为正的物品全部选出来,
然后记录一下从$1$开始可以覆盖到的最右端点的位置。
接下来开始DP,按照区间的端点升序排序(左端点第一关键字,右端点第二关键字)
问题转化为能否用剩下的物品覆盖尚未覆盖的区间。
那么直接用树状数组优化DP就可以了。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) #define fi first #define se second const int N = 1e5 + 10; struct node{ int s, t; double a, b; bool flag; void scan(){ scanf("%d%d%lf%lf", &s, &t, &a, &b); } friend bool operator < (const node &a, const node &b){ return a.s == b.s ? a.t < b.t : a.s < b.s; } } a[N]; int T; int n, m; double c[N]; double l, r; void update(int x, double val){ for (; x; x -= x & -x) c[x] = min(c[x], val); } double query(int x){ if (x == 0) return 0; double ret = 1e9; for (; x <= m; x += x & -x) ret = min(ret, c[x]); return ret; } bool check(double x){ int mx = 0; double ss = 0; rep(i, 0, m) c[i] = 1e9; rep(i, 1, n){ if (a[i].b * x - a[i].a > 0){ ss += a[i].b * x - a[i].a; a[i].flag = true; if (a[i].s - 1 <= mx){ mx = max(mx, a[i].t); } } else a[i].flag = false; } if (mx == m) return true; update(mx, 0); rep(i, 1, n){ if (!a[i].flag){ double mi = query(a[i].s - 1); update(a[i].t, mi + a[i].a - a[i].b * x); } else{ double mi = query(a[i].s - 1); update(a[i].t, mi); } } return ss >= query(m); } int main(){ scanf("%d", &T); while (T--){ scanf("%d%d", &n, &m); rep(i, 1, n) a[i].scan(); sort(a + 1, a + n + 1); l = 0, r = 1e3 + 10; rep(i, 1, 50){ double mid = (l + r) / 2.00; if (check(mid)) r = mid; else l = mid; } printf("%.3f\n", l); } return 0; }
原文地址:https://www.cnblogs.com/cxhscst2/p/8861918.html
时间: 2024-12-11 13:43:55