zoukankan      html  css  js  c++  java
  • jzoj 4475. 【GDOI2016模拟4.25】征途

    Description

    将n个数刚好分成m段,每段的贡献为此段数的和,求这m个数的最小方差*(m^2)
    对于 100% 的数据,1≤n≤3000。

    Solution

    由于是连续一段的,一眼斜率优化DP。
    (qz[i])表示(a[1])~(a[i])的和。
    我们考虑一下将答案化简。设平均数为(k)

    [ans=((x_1-k)^2+...+(x_m-k)^2)/m*m^2 ]

    [ans=((x_1)^2+...+(x_m)^2-2*(x_1+...+x_m)*k+m*k^2)*m ]

    [ans=m*((x_1)^2+...+(x_m)^2)-2*qz[n]^2+qz[n]^2 ]

    [ans=m*((x_1)^2+...+(x_m)^2)-qz[n]^2 ]

    因为要刚好分成(m)段,所以直接上凸优化。
    我们二分一个数,最后答案便是(f[n]-m*mid-qz[n]*qz[n])

    Code

    #include <cstdio>
    #include <cstring>
    #define N 3010
    #define ll long long
    #define mem(x, a) memset(x, a, sizeof x)
    #define fo(x, a, b) for (int x = a; x <= b; x++)
    using namespace std;
    int n, m, qz[N], g[N], l, len;
    ll f[N][2];
    
    inline int read()
    {
    	int x = 0; char c = getchar();
    	while (c < '0' || c > '9') c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    	return x;
    }
    
    int sqr(int x) {return x * x;}
    
    ll left(int x, int y) {return f[x][0] - f[y][0] + sqr(qz[x]) - sqr(qz[y]);}
    
    ll right(int x, int y) {return 2 * (qz[x] - qz[y]);}
    
    void check(int x)
    {
    	f[0][0] = 0, f[0][1] = 0;
    	g[l = len = 1] = 0;
    	fo(i, 1, n)
    	{
    		while (l < len && left(g[l + 1], g[l]) < right(g[l + 1], g[l]) * qz[i]) l++;
    		f[i][0] = f[g[l]][0] + sqr(qz[i] - qz[g[l]]) + x;
    		f[i][1] = f[g[l]][1] + 1;
    		while (l < len && left(g[len], g[len - 1]) * right(i, g[len]) >= left(i, g[len]) * right(g[len], g[len - 1])) len--;
    		g[++len] = i;
    	}
    }
    
    int main()
    {
    	freopen("journey.in", "r", stdin);
    	freopen("journey.out", "w", stdout);
    	n = read(), m = read(); qz[0] = 0;
    	fo(i, 1, n) qz[i] = qz[i - 1] + read();
    	check(0);
    	long long l = 0, r = 100000000000, mid;
    	while (l <= r)
    	{
    		mid = l + r >> 1;
    		check(mid);
    		if (f[n][1] == m) break;
    		if (f[n][1] < m) r = mid - 1;
    		else l = mid + 1;
    	}
    	printf("%d
    ", (f[n][0] - mid * m) * m - qz[n] * qz[n]);
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    nefu 628 Garden visiting
    codeforces 814 C. An impassioned circulation of affection 【尺取法 or DP】
    bzoj 2111: [ZJOI2010]Perm 排列计数 (dp+卢卡斯定理)
    Codeforces Round #423 (Div. 2)
    hdu 5955 Guessing the Dice Roll 【AC自动机+高斯消元】
    poj1322 Chocolate 【 概率DP 】
    poj 3414 Pots 【BFS+记录路径 】
    hdu5194 DZY Loves Balls 【概率论 or 搜索】
    51nod 1515 明辨是非 [并查集+set]
    hdu 1175 连连看 [DFS]
  • 原文地址:https://www.cnblogs.com/jz929/p/11300094.html
Copyright © 2011-2022 走看看