[Codeforces 868F]Yet Another Minimization Problem

Description

题库链接

给定一个序列 $a$,要把它分成 $k$ 个子段。每个子段的费用是其中相同元素的对数。求所有子段的费用之和的最小值。

$2 \leq n \leq 10^5,2 \leq k \leq \min(n,20),1 \leq a_i \leq n$

Solution

设 $f_{i,j}$ 表示 $1\sim i$ 分为 $j$ 段的最小费用。

那么 $f_{i,j}=\min\limits_{1\leq k\leq i}{f_{k-1,j-1}+w(k,i)}$。其中 $w(l,r)$ 表示区间 $[l,r]$ 这一段的费用。

并且可以知道 $\forall a<b<c<d,w(a,d)+w(b,c)\geq w(a,c)+w(b,d)$。证明的话可以对每个不同的数 $a$ 进行考虑,假设 $a\sim b$ 这段区间 $a$ 有 $x$ 个,$b\sim c$ 中有 $y$ 个,$c\sim d$ 中有 $z$ 个。然后可知 $w(a,d)=\frac{(1+x+y+z)(x+y+z)}{2}$,其余同理,之后暴力拆开可以直接证明。

满足四边形不等式后那么就可以在 $O(n\log n)$ 的时间内解决了。并且由于 $w(i,j)$ 运算复杂度较高,因此我们考虑分治。设 $[l,r]$ 是决策区间,$[L,R]$ 是更新区间。

在分治的过程中计算 $w$。由于每层重新清空重新计算 $w$ 的复杂度是伪的,具体是因为如果把 $r\sim MID(MID=(L+R)/2)$ 之间的数扫一遍的话复杂度是错的。

因此我们可以模拟莫队的操作只变更端点,这样复杂度可以保证,这是因为保存值的区间的左端点是随着 $[l,r]$ 变化的,右端点是随着 $[L,R]$ 变化的。每个变化都能保证复杂度是 $O(n\log n)$。

Code

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5+5;

int n, k, a[N], cnt[N], nl = 1, nr;
ll g[2][N], ans;

void cdq(int l, int r, int L, int R) {
    int MID = (L+R)>>1, mid, loc = MID, pl = nl, pr = nr;
    if (r < MID) loc = r;
    mid = loc;
    while (nr < MID) ans += cnt[a[++nr]]++;
    while (nl > loc) ans += cnt[a[--nl]]++;
    while (nr > MID) ans -= --cnt[a[nr--]];
    while (nl < loc) ans -= --cnt[a[nl++]];
    g[1][MID] = g[0][loc-1]+ans;
    for (int i = loc-1; i >= l; i--) {
        ans += cnt[a[i]]++;
        if (g[0][i-1]+ans < g[1][MID])
            mid = i, g[1][MID] = g[0][i-1]+ans;
    }
    nl = l;
    if (L < MID) cdq(l, mid, L, MID-1);
    if (MID < R) cdq(mid, r, MID+1, R);
    while (nr < pr) ans += cnt[a[++nr]]++;
    while (nl > pl) ans += cnt[a[--nl]]++;
    while (nr > pr) ans -= --cnt[a[nr--]];
    while (nl < pl) ans -= --cnt[a[nl++]];
}
int main() {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    memset(g[0], 127/3, sizeof(g[0]));
    g[0][0] = 0;
    while (k--) {
        cdq(1, n, 1, n);
        swap(g[0], g[1]);
    }
    printf("%lld\n", g[0][n]);
    return 0;
}
posted @ 2020-02-21 17:21  NaVi_Awson  阅读(181)  评论(0编辑  收藏  举报