[ABC355G] Baseball 题解
简化题意:选择
可以转化为(此处设
设
设
代码:
#include<cstdio>
#include<algorithm>
#define ll long long
#define N 50010
#define pa pair<ll,int>
using namespace std;
int n, k;
ll p[N], sl[N], ssl[N], sr[N], ssr[N], c;
pa f[N], ans;
int id[N], bg, en, ql[N], qr[N];
ll wl(int l, int r)
{
if(l > r)return 0;
return ssr[l] - ssr[r + 1] - sr[r + 1] * (r - l + 1);
}
ll wr(int l, int r)
{
if(l > r)return 0;
return ssl[r] - ssl[l - 1] - sl[l - 1] * (r - l + 1);
}
ll w(int l, int r)
{
if(l + 1 == r)return 0;
int mid = (l + r) / 2;
return wl(l + 1, mid) + wr(mid + 1, r - 1);
}
pa get(int l, int r)
{
return make_pair(f[l].first + w(l, r) + c, f[l].second + 1);
}
void check()
{
bg = 1;
en = 0;
ans = make_pair(1e18, 0);
for(int i = 1; i <= n; i++)
{
f[i] = make_pair(wr(1, i - 1) + c, 1);
while(bg <= en && qr[bg] < i)bg++;
if(bg <= en)
{
ql[bg] = i + 1;
f[i] = min(f[i], get(id[bg], i));
}
ans = min(ans, make_pair(f[i].first + wl(i + 1, n), f[i].second));
while(bg <= en && get(i, ql[en]) < get(id[en], ql[en]))en--;
if(bg > en)
{
bg = en = 1;
id[bg] = i;
ql[bg] = i + 1;
qr[bg] = n;
}
else if(get(i, qr[en]) > get(id[en], qr[en]))
{
if(qr[en] < n)
{
en++;
ql[en] = qr[en - 1] + 1;
qr[en] = n;
id[en] = i;
}
}
else
{
int ml = ql[en], mr = qr[en];
while(ml < mr)
{
int mid = (ml + mr) / 2;
if(get(i, mid) < get(id[en], mid))mr = mid;
else ml = mid + 1;
}
qr[en] = ml - 1;
en++;
ql[en] = ml;
qr[en] = n;
id[en] = i;
}
}
}
int main()
{
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i++)scanf("%lld", p + i);
for(int i = 1; i <= n; i++)sl[i] = sl[i - 1] + p[i], ssl[i] = ssl[i - 1] + sl[i];
for(int i = n; i; i--)sr[i] = sr[i + 1] + p[i], ssr[i] = ssr[i + 1] + sr[i];
ll ml = 0, mr = 1e10;
while(ml < mr)
{
c = (ml + mr) / 2;
check();
if(ans.second <= k)mr = c;
else ml = c + 1;
}
c = ml;
check();
printf("%lld\n", ans.first - k * c);
return 0;
}