#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
#define endl "\n"
#define ll long long
#define IOS ios_base::sync_with_stdio(false); cin.tie(nullptr);
const int N = 1e5 + 5;
const double INF = 1e18;
const int MAX = 1e6;
long long a[N];
pair<long double, int> dp[N];
struct Line {
double k, b; int j;
pair<double, int> f(double x) {
return make_pair(k * x + b, j);
}
Line(double k, double b, int j) : k(k), b(b), j(j) {}
};
struct Node {
Line line;
int left;
int right;
Node(Line line) : line(line), left(-1), right(-1) {}
Node() : line(0, -INF, 0), left(-1), right(-1) {}
};
Node nodes[MAX];
int idx = 0;
void add(int l, int r, int node, Line cur) {
if (l > r) {
return;
}
int mid = (l + r) / 2;
if (r - l == 1 && mid == r) {
mid--;
}
bool lf = cur.f(l) > nodes[node].line.f(l);
bool md = cur.f(mid) > nodes[node].line.f(mid);
if (md) {
swap(nodes[node].line, cur);
}
if (l == r) {
return;
}
if (lf != md) {
if (nodes[node].left == -1) {
nodes[node].left = idx;
nodes[idx++] = Node(cur);
} else {
add(l, mid, nodes[node].left, cur);
}
} else {
if (nodes[node].right == -1) {
nodes[node].right = idx;
nodes[idx++] = Node(cur);
} else {
add(mid + 1, r, nodes[node].right, cur);
}
}
return;
}
pair<double, int> query(int l, int r, int node, int x) {
if (l > r) {
return make_pair(-INF, 0);
}
int mid = (l + r) / 2;
if (r - l == 1 && mid == r) {
mid--;
}
pair<double, int> ans = nodes[node].line.f((double)x);
if (l == r) {
return ans;
}
if (x <= mid && nodes[node].left != -1) {
ans = max(ans, query(l, mid, nodes[node].left, x));
}
if (x > mid && nodes[node].right != -1) {
ans = max(ans, query(mid + 1, r, nodes[node].right, x));
}
return ans;
}
pair<double, int> calc(int n, double cost) {
idx = 0;
nodes[idx++] = Node();
Line line((double)1.0 / (double)n, 0, 0);
add(0, N - 1, 0, line);
for (int i = 1; i <= n; i++) {
pair<double, int> q = query(0, N - 1, 0, i);
dp[i] = make_pair(q.first - cost, q.second + 1);
if (i != n) {
Line line = Line((double)1.0 / (double)(n - i), dp[i].first - (double)i / (double)(n - i), dp[i].second);
add(0, N - 1, 0, line);
}
/*for (int j = i - 1; j >= 0; j--) {
dp[i] = max(dp[i], make_pair(dp[j].first - cost + (long double)(i - j) / (long double)(n - j), dp[j].second + 1));
}*/
}
return dp[n];
}
int main() {
IOS;
cout << fixed;
cout << setprecision(12);
int n, k;
cin >> n >> k;
double l = 0, r = 50, opt = 0;
for (int i = 0; i < 40; i++) {
double mid = (l + r) / 2;
if (calc(n, mid).second >= k) {
opt = mid;
l = mid;
} else {
r = mid;
}
}
double ans = calc(n, opt).first + opt * k;
cout << ans;
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |