107 lines
3.1 KiB
C++
107 lines
3.1 KiB
C++
#include <cstdio>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
using namespace std;
|
|
typedef long long LL;
|
|
typedef long double LDB;
|
|
const int kMaxN = 1e5 + 10;
|
|
int N, S;
|
|
LDB A[kMaxN], B[kMaxN], R[kMaxN];
|
|
struct NodeType {
|
|
int rawid;
|
|
LDB a, b, r, f;
|
|
};
|
|
NodeType nodes[kMaxN];
|
|
inline LDB GetX(const NodeType &node) {
|
|
return node.f * node.r / (node.a * node.r + node.b);
|
|
}
|
|
inline LDB GetY(const NodeType &node) {
|
|
return node.f / (node.a * node.r + node.b);
|
|
}
|
|
bool CmpX(const NodeType &na, const NodeType &nb) {
|
|
return GetX(na) < GetX(nb);
|
|
}
|
|
bool CmpId(const NodeType &na, const NodeType &nb) {
|
|
return na.rawid < nb.rawid;
|
|
}
|
|
bool CmpK(const NodeType &na, const NodeType &nb) {
|
|
return -na.a / na.b > -nb.a / nb.b;
|
|
}
|
|
int Q[kMaxN], QL, QR;
|
|
typedef bool (*CmpType)(const NodeType &, const NodeType &);
|
|
void MergeSort(NodeType *beg, NodeType *end, CmpType cmp) {
|
|
if (end - beg <= 1) return;
|
|
size_t len = end - beg;
|
|
NodeType *mid = beg + (len >> 1);
|
|
MergeSort(beg, mid, cmp);
|
|
MergeSort(mid, end, cmp);
|
|
NodeType *tmp = new NodeType[len];
|
|
NodeType *cur_tmp = tmp, *cur_L = beg, *cur_R = mid;
|
|
while ((cur_L < mid) && (cur_R < end)) {
|
|
if (cmp(*cur_L, *cur_R))
|
|
*(cur_tmp++) = *(cur_L++);
|
|
else
|
|
*(cur_tmp++) = *(cur_R++);
|
|
}
|
|
while (cur_L < mid) *(cur_tmp++) = *(cur_L++);
|
|
while (cur_R < end) *(cur_tmp++) = *(cur_R++);
|
|
cur_tmp = tmp;
|
|
NodeType *cur_dst = beg;
|
|
while (cur_dst < end) *(cur_dst++) = *(cur_tmp++);
|
|
delete[] tmp;
|
|
}
|
|
void CDQ(int L, int R) {
|
|
if (L == R) return;
|
|
int M = (L + R) >> 1;
|
|
CDQ(L, M);
|
|
MergeSort(nodes + L, nodes + M + 1, CmpX);
|
|
MergeSort(nodes + M + 1, nodes + R + 1, CmpK);
|
|
Q[QL = QR = 0] = L;
|
|
for (int i = L + 1; i <= M; i++) {
|
|
while (QR - QL + 1 >= 2 &&
|
|
(GetX(nodes[Q[QR]]) - GetX(nodes[Q[QR - 1]])) *
|
|
(GetY(nodes[i]) - GetY(nodes[Q[QR - 1]])) -
|
|
(GetY(nodes[Q[QR]]) - GetY(nodes[Q[QR - 1]])) *
|
|
(GetX(nodes[i]) - GetX(nodes[Q[QR - 1]])) >=
|
|
0)
|
|
QR--;
|
|
Q[++QR] = i;
|
|
}
|
|
LDB base = 0;
|
|
for (int i = L; i <= M; i++) base = max(base, nodes[i].f);
|
|
for (int i = M + 1; i <= R; i++) {
|
|
while (QR - QL + 1 >= 2 &&
|
|
(GetY(nodes[Q[QL + 1]]) - GetY(nodes[Q[QL]])) /
|
|
(GetX(nodes[Q[QL + 1]]) - GetX(nodes[Q[QL]])) >=
|
|
-nodes[i].a / nodes[i].b)
|
|
QL++;
|
|
nodes[i].f = max(nodes[i].f, base);
|
|
nodes[i].f = max(nodes[i].f, nodes[i].a * GetX(nodes[Q[QL]]) +
|
|
nodes[i].b * GetY(nodes[Q[QL]]));
|
|
}
|
|
MergeSort(nodes + M + 1, nodes + R + 1, CmpId);
|
|
CDQ(M + 1, R);
|
|
}
|
|
int main() {
|
|
#ifdef local
|
|
freopen("pro.in", "r", stdin);
|
|
#endif
|
|
scanf("%d%d", &N, &S);
|
|
for (int i = 1; i <= N; i++) {
|
|
scanf("%Lf%Lf%Lf", &A[i], &B[i], &R[i]);
|
|
nodes[i].rawid = i;
|
|
nodes[i].a = A[i];
|
|
nodes[i].b = B[i];
|
|
nodes[i].r = R[i];
|
|
}
|
|
nodes[1].f = S;
|
|
CDQ(1, N);
|
|
// for (int i = 1; i <= N; i++)
|
|
// printf("f(%d)=%.3Lf\n", nodes[i].rawid, nodes[i].f);
|
|
for (int i = 1; i <= N; i++)
|
|
if (nodes[i].rawid == N) {
|
|
printf("%.3Lf\n", nodes[i].f);
|
|
return 0;
|
|
}
|
|
return 0;
|
|
} |