CF868F Yet Another Minimization Problem
题面
题解
转移方程非常套路
然后可以发现可以决策单调性
由于每次转移的贡献不能O(1)算,显然应该考虑分治实现
贡献可以考虑像莫队一样移
复杂度不会证
#include<bits/stdc++.h> using namespace std; inline int read() { int f = 1,x = 0; char ch; do { ch = getchar(); if(ch == '-') f = -1; }while(ch < '0' || ch > '9'); do { x = (x<<3) + (x<<1) + ch - '0'; ch = getchar(); }while(ch >= '0' && ch <= '9'); return f*x; } #define ll long long #define re register const int MAXN = 1e5 + 10; int a[MAXN]; ll dp[20 + 2][MAXN]; ll cnt[MAXN]; int L,R,n,k; ll ans; inline void update(int x,int d) { ans += 1LL * d * (cnt[a[x]]) * (cnt[a[x]]-1)/2; return; } inline ll calc(int l,int r) { while(l<L) L--,update(L,-1),cnt[a[L]]++,update(L,1); while(l>L) update(L,-1),cnt[a[L]]--,update(L,1),L++; while(r<R) update(R,-1),cnt[a[R]]--,update(R,1),R--; while(r>R) R++,update(R,-1),cnt[a[R]]++,update(R,1); return ans; } inline void solve(int k,int dL,int dR,int l,int r) { //cout << dp[k][n] << endl; if(dL>dR||l>r) return; int mid = (l+r)>>1,d = 0; for(int i=dL;i<=dR&&i<mid;i++) { ll res = calc(i+1,mid); if(dp[k][mid]>dp[k-1][i]+res) { dp[k][mid] = dp[k-1][i] + res; d = i; } } solve(k,dL,d,l,mid-1);solve(k,d,dR,mid+1,r); } int main() { n = read();k = read(); memset(dp,127,sizeof(dp));dp[0][0]=0; for(re int i=1;i<=n;i++) a[i] = read(); cnt[a[1]]++;L = 1,R = 1; for(re int i=1;i<=k;i++)solve(i,0,n-1,1,n); printf("%lld ",dp[k][n]); return 0; }