Files
SH-Quizzes/ACMOJ-2148.cpp
2024-04-18 18:38:55 +08:00

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