• 【洛谷P4983】忘情


    题目

    题目链接:https://www.luogu.com.cn/problem/P4983
    你的 (npy) 为了恶心你,特地请了四位大神和一个辣鸡!
    ( m hdxrie) 说:“我们得求和。”于是有了 (sumlimits_{i=1}^{n}x_i)
    ( m Imagine) 说:“我们得有平均数。”于是有了 (ar x)
    ( m TimeTraveller) 说:“我们得有加减乘除。”于是有了一些恶心的组合。
    ( m Althen·Way·Satan) 说:“我们还得有平方。”于是我们将它平方。
    最垃圾的 ( m ZredXNy) 说:“那我帮你们整合一下。”
    于是,我们得到了这么一个式子 (:)

    [frac{left((sumlimits_{i=1}^{n}x_i×ar x)+ar x ight)^2}{ar x^2} ]

    我们定义一段序列的值为这个,其中 (n) 为此序列的元素个数。
    我们给定一段长度为 (n) 的序列,现在要求将它分成 (m) 段,要求每一段的值的总和最小,求出这个最小值。
    (mleq nleq 10^5,x_ileq 10^3)

    思路

    其实那一坨式子就等于 ((sum x_i+1)^2)
    我们记 (g_i) 表示分为 (i) 段后每一段和的最小值,假设这次合并的两段的区间和分别为 (x,y),那么有 (g_i-g_{i-1}=(x+y+1)^2-(x+1)^2-(y+1)^2=2xy-1)。由于我们每次选择的相邻两段长度乘积 (xy) 肯定不会降,所以 (g_i-g_{i-1}) 是单调不降的,所以 (g_i) 是一个下凸函数。
    又因为题目要求恰好分为 (m) 段,考虑 wqs 二分。设 (f_i) 表示前 (i) 个数字分成若干段的最小代价,那么有

    [f_i=min(f_j+(s_i-s_j+1)^2-mid) ]

    其中 (s)(x) 的前缀和。
    一眼就能看出这是一个斜率优化的板子题。直接用单调队列维护一下下凸壳即可。
    时间复杂度 (O(nlog V))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=100010;
    int n,m,a[N],q[N],g[N];
    ll ans,f[N],X[N],Y[N];
    
    double slope(int i,int j)
    {
    	return 1.0*(Y[i]-Y[j])/(X[i]-X[j]);
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		a[i]+=a[i-1];
    	}
    	ll l=0,r=1e18,mid;
    	while (l<=r)
    	{
    		mid=(l+r)>>1;
    		int hd=1,tl=1;
    		for (int i=1;i<=n;i++)
    		{
    			while (tl>hd && slope(q[hd],q[hd+1])<a[i]) hd++;
    			f[i]=f[q[hd]]+1LL*(a[i]-a[q[hd]]+1)*(a[i]-a[q[hd]]+1)+mid;
    			g[i]=g[q[hd]]+1;
    			X[i]=2LL*a[i]; Y[i]=f[i]+1LL*a[i]*a[i]-2LL*a[i];
    			while (tl>hd && slope(q[tl],q[tl-1])>slope(i,q[tl])) tl--;
    			q[++tl]=i;
    		}
    		if (g[n]<=m) ans=f[n]-mid*m,r=mid-1;
    			else l=mid+1;
    	}
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    CodingTrip
    CodingTrip
    Linux下面查找含有特定的字符的文件
    Linux下TCP/IP协议的Socket编程
    显示Apache服务器里面访问量排在前10的ip地址
    c语言的详细编译过程
    WebStorm设置编辑器中的字体大小
    Sublime多行编辑快捷键
    Aptana 中去掉“Missing semicolon”提醒
    公认的媒体类型
  • 原文地址:https://www.cnblogs.com/stoorz/p/15012526.html
Copyright © 2020-2023  润新知