Yet Another Minimization Problem
dp方程我们很容易能得出, f[ i ] = min(g[ j ] + w( j + 1, i ))。 然后感觉就根本不能优化。
然后就滚去学决策单调啦。 然后就是个裸题, 分治一下就好啦,
注意用分治找决策点需要的条件是我们找出被决策点不能作为当前转移的决策点使用。
如果w( j + 1, i )能很方便求出就能用单调栈维护, 并且找出的被决策点能当作当前转移的决策点使用。
我怎么感觉用bfs应该跑莫队的时候应该比dfs快啊, 但是居然还是dfs跑得快, 莫名其妙。。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); int n, k, a[N], cnt[N]; LL f[N], g[N]; int pl = 1, pr = 0; LL val; inline LL w(int i, int j) { while(pl > i) pl--, val += cnt[a[pl]], cnt[a[pl]]++; while(pr < j) pr++, val += cnt[a[pr]], cnt[a[pr]]++; while(pl < i) cnt[a[pl]]--, val -= cnt[a[pl]], pl++; while(pr > j) cnt[a[pr]]--, val -= cnt[a[pr]], pr--; return val; } void solve(int L, int R, int l, int r) { if(l > r) return; int mid = l + r >> 1, p = L; for(int i = L; i <= min(R, mid); i++) if(g[i] + w(i + 1, mid) < f[mid]) f[mid] = g[i] + w(i + 1, mid), p = i; solve(L, p, l, mid - 1); solve(p, R, mid + 1, r); } int main() { scanf("%d%d", &n, &k); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); f[i] = f[i - 1] + cnt[a[i]]; cnt[a[i]]++; } for(int i = 2; i <= k; i++) { memset(cnt, 0, sizeof(cnt)); memcpy(g, f, sizeof(g)); memset(f, INF, sizeof(f)); solve(1, n, 1, n); } printf("%lld ", f[n]); return 0; } /* */