BZOJ4709: [Jsoi2011] lemon (slope optimization)

Posted by Birdfeed on Wed, 18 Dec 2019 20:09:47 +0100

meaning of the title

Title Link

Sol

Conclusion: the interval of each selection must satisfy the same first element..

If you think about it carefully, it is quite obvious that if you are different, you can delete many elements, and your contribution to the answer is the same

Then let \ (f[i] \) represent the maximum value to \ (I \) position, \ (s[i] \) represent to \ (I \) position, and \ (a[i] \) appear times. The transfer equation is

\[f[i] = max(f_{j - 1} + a[i] * (s[i] - s[j] +1)^2)\]

Meet \ (a[i] = a[j] \)

It looks like the slope can be optimized, but there is another explanation..

Concrete look Here bar

I feel that my slope is better than that of chemistry

#include<bits/stdc++.h>
#define chmax(a, b) (a = (a > b ? a : b))
#define chmin(a, b) (a = (a < b ? a : b))
#define LL long long
//#define int long long 
using namespace std;
const int MAXN = 1e6 + 10;
inline int read() {
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, a[MAXN], s[MAXN], cnt[MAXN]; LL f[MAXN];//What i s the number of s[i] i positions?
vector<int> v[MAXN];
LL calc(int pos, LL val) {
    return f[pos - 1] + 1ll * a[pos] * val * val;
}
int lower(int x, int y) {
    int l = 1, r = N, ans = N + 1;
    while(l <= r) {
        int mid = l + r >> 1;
        if(calc(x, mid - s[x] + 1) >= calc(y, mid - s[y] + 1)) r = mid - 1, ans = mid;
        else l = mid + 1;
    }
    return ans;
}
main() {
    N = read();
    for(int i = 1, siz, S; i <= N; i++) {
        s[i] = ++cnt[S = a[i] = read()];
        while((((siz = v[S].size()) >= 2) && (lower(v[S][siz - 2], v[S][siz - 1]) <= lower(v[S][siz - 1], i)))) v[S].pop_back();
        v[S].push_back(i);
        while(((siz = v[S].size()) >= 2) && (lower(v[S][siz - 2], v[S][siz - 1]) <= s[i]))v[S].pop_back();
        f[i] = calc(v[S][v[S].size() - 1], s[i] - s[v[S][v[S].size() - 1]] + 1);
    }
    cout << f[N];
}

Topics: C++