Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <iostream>
- #include <numeric>
- #include <cassert>
- #include <vector>
- typedef long long llong;
- const int MAXN = 200000 + 10;
- const llong INF = 1e18;
- const int INTINF = 2e9;
- const int MAXSQ = 450;
- struct ConvexHullTrick
- {
- struct CHTElement
- {
- llong x, y;
- llong to;
- llong at(llong t)
- {
- return x * t + y;
- }
- };
- llong intersect(CHTElement left, CHTElement right)
- {
- return (right.y - left.y) / (left.x - right.x);
- }
- std::vector <CHTElement> cht;
- void push(llong x, llong y)
- {
- if (cht.size() && cht.back().y >= y)
- {
- return;
- }
- if (cht.size()) assert(cht.back().x >= x);
- CHTElement newElement = {x, y, INTINF};
- while (cht.size() && cht.back().at(cht.back().to) <= newElement.at(cht.back().to))
- {
- cht.pop_back();
- }
- if (cht.empty()) cht.push_back(newElement);
- else
- {
- cht.push_back({x, y, intersect(cht.back(), newElement)});
- }
- }
- llong search(llong x)
- {
- if (cht.empty())
- {
- return -INF;
- }
- int l = 0, r = cht.size(), mid;
- while (l < r - 1)
- {
- mid = (l + r) / 2;
- if (x <= cht[mid].to) l = mid;
- else r = mid;
- }
- return cht[l].at(x);
- }
- };
- int n;
- llong a[MAXN];
- bool isComposite[MAXN];
- ConvexHullTrick cht[MAXSQ][MAXSQ];
- std::vector <int> primes;
- llong dp[MAXN];
- llong max_prize(std::vector <int> A)
- {
- n = A.size();
- for (int i = 1 ; i <= n ; ++i)
- {
- a[i] = A[i - 1];
- }
- for (int i = 2 ; i * i <= n ; ++i)
- {
- if (!isComposite[i])
- {
- primes.push_back(i);
- for (int j = i * i ; j * j <= n ; j += i)
- {
- isComposite[j] = true;
- }
- }
- }
- dp[1] = 0;
- for (const int &p : primes)
- {
- cht[p][1].push(0, dp[1]);
- }
- llong oneAnswer = -INF;
- for (int i = 2 ; i <= n ; ++i)
- {
- dp[i] = -INF;
- if (i > 2) dp[i] = oneAnswer + a[i];
- if (a[i] > 0)
- {
- for (const int &p : primes)
- {
- if (cht[p][i % p].cht.empty()) continue;
- dp[i] = std::max(dp[i], 1LL * a[i] * (i / p) + cht[p][i % p].search(a[i]));
- }
- }
- oneAnswer = std::max(oneAnswer, dp[i - 1]);
- if (dp[i] == -INF) continue;
- for (const int &p : primes)
- {
- cht[p][i % p].push(-(i / p), dp[i]);
- }
- }
- return dp[n];
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement