#include #include #include 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; }