제출 #1260408

#제출 시각아이디문제언어결과실행 시간메모리
1260408LucasLe수열 (APIO14_sequence)C++17
100 / 100
1529 ms88452 KiB
#include <bits/stdc++.h>
 
const int maxn = 1e5 + 5;
const long long INF = 1e18;
 
int n, k;
int trace[maxn + 5][205];
int a[maxn + 5], pref[maxn + 5];
long long f_prev[maxn + 5], f[maxn + 5];
 
long long divi(long long x, long long y) {
        if (!x || !y) return 0ll;
        return x / y - ((x ^ y) < 0 && x % y);
}
 
struct line {
        int pos;
        long long a, b;
        line(long long _a, long long _b, int _pos) : a(_a), b(_b), pos(_pos) {}
        long long operator () (long long x) { return a * x + b; }
        long long intersect(const line &other) {
                return divi(other.b - b, a - other.a);
        }
};
 
struct CHT {
        std::vector<line> data_line;
        
        void add(line d) {
                // line l1,l2,l3;
                while ((int)data_line.size() >= 2) {

                        line l1=data_line[(int)data_line.size() - 2];
                        line l2=data_line[(int)data_line.size() - 1];
                        line l3=d;
                        long long b23 = l3.b - l2.b;
                        long long a23 = l2.a - l3.a;

                        long long b12 = l2.b - l1.b;
                        long long a12 = l1.a - l2.a;

                          if (a23 < 0) {
                            b23 *= -1;
                            a23 *= -1;
                          }

                          if (a12 < 0) {
                            b12 *= -1;
                            a12 *= -1;
                          }

                        if (b23 * a12 >= b12 * a23)
                                data_line.pop_back();
                        else
                                break;
                }
                data_line.push_back(d);
        }
 
        int query(long long x) {
                int l = 0, r = (int)data_line.size() - 1, pos;
                while (l <= r) {
                        int mid = (l + r) >> 1;
                        if (!mid) {
                          pos=mid;
                          l=mid+1;
                          continue;
                        }

                        line l1 = data_line[mid];
                        line l2 = data_line[mid - 1];
                        long long b12=(l2.b-l1.b);
                        long long a12=(l1.a-l2.a);
                        if(a12<0){
                            a12*=-1;
                            b12*=-1;
                        }

                        if (b12 < x * a12) {
                                r = mid - 1;
                        } else {
                                l = mid + 1;
                                pos = mid;
                        }
                }
                line d = data_line[pos];
                return d.pos;
        }
};
 
void solve() {
        std::cin >> n >> k;
        for (int i = 1; i <= n; ++i) std::cin >> a[i];
        for (int i = 1; i <= n; ++i) pref[i] = pref[i - 1] + a[i];
 
        for (int i = 1; i < n; ++i)
                f_prev[i] = 1ll * (pref[n] - pref[i]) * pref[i];
 
        int pos_ans;
        long long ans = -1;        
 
        if (k == 1) {
                for (int i = 1; i < n; ++i)
                        if (ans < f_prev[i]) {
                                ans = f_prev[i];
                                pos_ans = i;
                        }
                std::cout << ans << '\n';
                std::cout << pos_ans;
                return;
        }
 
        for (int j = 2; j <= k; ++j) {
                CHT lc;
                for (int i = j; i < n; ++i) {
                        // f[i][j] = (pref[i] - pref[l]) * (pref[n] - pref[i]) + f[l][j - 1];
                        //         = (pref[n] - pref[i]) * pref[i] - (pref[n] - pref[i]) * pref[l] + f[l][j - 1];
                        lc.add(line(1ll * -pref[i - 1], f_prev[i - 1], i - 1));
                        int pos = lc.query(1ll * pref[n] - pref[i]);
                        f[i] = 1ll * (pref[n] - pref[i]) * pref[i] + 1ll * -pref[pos] * (pref[n] - pref[i]) + f_prev[pos];
                        trace[i][j] = pos;
                        if (j == k) {
                                if (ans < f[i]) {
                                        ans = f[i];
                                        pos_ans = i;
                                }
                        }
                }
                for (int i = 1; i < n; ++i) f_prev[i] = f[i];
        }
 
        std::vector<int> pos_vec;
        while (k) {
                assert(pos_ans > 0);
                pos_vec.push_back(pos_ans);
                pos_ans = trace[pos_ans][k];
                k--;
        }
        
        reverse(pos_vec.begin(), pos_vec.end());
        std::cout << ans << '\n';
        for (int x : pos_vec) std::cout << x << ' ';
}
 
int main() {
        std::ios_base::sync_with_stdio(false);
        std::cin.tie(0);
 
        int tc = 1;
        // std::cin >> tc;
        while (tc--)
                solve();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...