zoukankan      html  css  js  c++  java
  • CodeForces

    Description

    给定一个长度为 (n(nle 10^5)) 的数列,第 (i) 个数是 (a_iin[1,n]) ,要求将其划分为 (k(2le kle min(20,n))) 段以后每段价值和最小。

    定义一段的价值为该段相同数的数对个数。

    Solution

    定义 (calc(l,r))([l,r]) 这一段的价值, (dp[j][i]) 为前 (i) 个数划分为 (j) 段的最小价值。那么显然有

    [dp[j][i]=min{dp[j-1][i']+calc(i'+1,i),i'<i} ]

    因为 (dp[j][i]) 仅由 (dp[j-1][i']) 转移来,不妨设 (j) 固定。

    (f(i)) 表示 (i) 对应的最优决策点 (i')打表不难发现 (f(i)) 单调递增。

    考虑分治。(solve(l,r,L,R)) 表示对于 (iin [l,r]) ,有 (f(i)in {L,R}) 。枚举出 (mid=cfrac{l+r}{2}) 的决策点 (f(mid)) 后分治 (solve(l,mid-1,L,f(mid)))(solve(mid+1,r,f(mid),R)) 即可。

    对于 (calc(l,r)) ,因为 (l)(r) 的每次移动后都可以 (O(1)) 计算答案,所以可以莫队。

    #include<bits/stdc++.h>
    using namespace std;
    
    template <class T> inline void read(T &x) {
    	x = 0; static char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar());
    	for (; ch >= '0' && ch <= '9'; ch = getchar()) (x *= 10) += ch - '0';
    }
    
    #define N 100001
    #define rep(i, a, b) for (int i = a; i <= b; i++)
    #define ll long long
    
    const ll INF = 0x3f3f3f3f3f3f3f3f, P = 1e9 + 7;
    int n, K, a[N], now, nxt = 1, lf = 1, ri, cnt[N];
    ll dp[2][N], sum;
    
    inline void calc(int l, int r) {
    	while (ri < r) sum += cnt[a[++ri]], cnt[a[ri]]++;
    	while (ri > r) cnt[a[ri]]--, sum -= cnt[a[ri--]];
    	while (lf > l) sum += cnt[a[--lf]], cnt[a[lf]]++;
    	while (lf < l) cnt[a[lf]]--, sum -= cnt[a[lf++]];
    }
    
    #define mid (l + r >> 1)
    void solve(int l, int r, int L, int R) {
    	if (l > r) return;
    	dp[nxt][mid] = INF;
    	int t;
    	rep(i, L, min(mid, R)) {
    		calc(i, mid);
    		if (dp[nxt][mid] > dp[now][i - 1] + sum) dp[nxt][mid] = dp[now][i - 1] + sum, t = i;
    	}
    	solve(l, mid - 1, L, t), solve(mid + 1, r, t, R);
    }
    
    int main() {
    	read(n), read(K);
    	rep(i, 1, n) read(a[i]);
    	memset(dp, INF, sizeof dp); dp[now][0] = 0;
    	while (K--) solve(1, n, 1, n), swap(now, nxt);
    	printf("%lld", dp[now][n]);
    	return 0;
    }
    
  • 相关阅读:
    HDU 1525
    kmp模板
    hdu 4616 Game(树形DP)
    hdu 4619 Warm up 2(并查集活用)
    hdu 4614 Vases and Flowers(线段树加二分查找)
    Codeforces 400D Dima and Bacteria(并查集最短路)
    poj 2823 Sliding Window (单调队列)
    hdu 2196 Computer(树形dp)
    hdu 4604 Deque
    最短路径
  • 原文地址:https://www.cnblogs.com/aziint/p/9189225.html
Copyright © 2011-2022 走看看