CDQ分治论文题
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-9
#define LL long long
#define pii pair<int, int>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn = 100000 + 1000;
int n;
double ans[maxn];
struct Point {
double a, b, r;
double x, y, k;
int id;
bool operator < (const Point& A) const {
return x < A.x;
}
} p[maxn], t[maxn];
int S[maxn];
double getK(int a, int b) {
if(!b) return 1e-20;
if(fabs(p[a].x-p[b].x) < eps) return 1e20;
return (p[b].y-p[a].y) / (p[b].x-p[a].x);
}
bool cmp(const Point A, const Point B) {
return A.k > B.k;
}
void CDQ(int L, int R) {
if(L == R) {
ans[L] = max(ans[L], ans[L-1]);
p[L].y = ans[L]/(p[L].r*p[L].a+p[L].b);
p[L].x = p[L].y*p[L].r;
return;
}
int mid = (L+R) >> 1;
int l1 = L, l2 = mid + 1;
for(int i = L; i <= R; i++) {
if(p[i].id > mid) t[l2++] = p[i];
else t[l1++] = p[i];
}
for(int i = L; i <= R; i++) p[i] = t[i];
CDQ(L, mid);
int top = 0, pos = 1;
for(int i = L; i <= mid; i++) {
while(top>1 && getK(S[top-1], S[top])<getK(S[top-1], i)+eps)
top--;
S[++top] = i;
}
for(int i = mid+1; i <= R; i++) {
while(pos<top && getK(S[pos], S[pos+1])+eps>p[i].k) pos++;
ans[p[i].id] = max(ans[p[i].id], p[i].a*p[S[pos]].x+p[i].b*p[S[pos]].y);
}
CDQ(mid+1, R);
merge(p+L, p+mid+1, p+mid+1, p+R+1, t+L);
for(int i = L; i <= R; i++) p[i] = t[i];
}
int main() {
//freopen("input.txt", "r", stdin);
scanf("%d%lf", &n, &ans[0]);
for(int i = 1; i <= n; i++) {
scanf("%lf%lf%lf", &p[i].a, &p[i].b, &p[i].r);
p[i].k = -p[i].a/p[i].b;
p[i].id = i;
}
sort(p+1, p+n+1, cmp);
CDQ(1, n);
printf("%.3lf", ans[n]);
return 0;
}