【HNOI 2008】玩具装箱

传送门


Problem

给出一个长度为 n n n 的序列 { a n } \{a_n\} {an} 以及常数 m m m,现要将它分成若干段,对于一个 [ i , j ] [i,j] [i,j] 的区间的贡献是 ( j − i + ∑ k = i j a k − m ) 2 (j-i+\sum\limits_{k=i}^ja_k-m)^2 (ji+k=ijakm)2,求总贡献的最小值。

数据范围: 1 ≤ n ≤ 50000 1\le n\le50000 1n50000 1 ≤ n , a i ≤ 1 0 7 1\le n,a_i\le10^7 1n,ai107


Solution

我们定义 S i S_i Si a i a_i ai 的前缀和, f i f_i fi 为在 i i i i + 1 i+1 i+1 分割一次的最小费用。

那么有

f i = min ⁡ j = 1 i − 1 { f j + ( i − j − 1 + ( S i − S j ) − m ) 2 } f_i=\min_{j=1}^{i-1}\{f_j+(i-j-1+(S_i-S_j)-m)^2\} fi=j=1mini1{fj+(ij1+(SiSj)m)2}

那我们令 G i = S i + i G_i=S_i+i Gi=Si+i(为了方便化简),得:

f i = min ⁡ j = 1 i − 1 { f j + ( G i − G j − ( m + 1 ) ) 2 } f_i=\min_{j=1}^{i-1}\{f_j+(G_i-G_j-(m+1))^2\} fi=j=1mini1{fj+(GiGj(m+1))2}

于是选择任意的 k &lt; j &lt; i k&lt;j&lt;i k<j<i,当 j j j k k k 优时,有(接下来就是把平方拆开然后化简,就不写了):

( f j + G j 2 + 2 ( m + 1 ) G j ) − ( f k + G k 2 + 2 ( m + 1 ) G k ) G j − G k &lt; 2 G i \frac{(f_j+G_j^2+2(m+1)G_j)-(f_k+G_k^2+2(m+1)G_k)}{G_j-G_k}&lt;2G_i GjGk(fj+Gj2+2(m+1)Gj)(fk+Gk2+2(m+1)Gk)<2Gi

然后维护一个下凸壳转移即可。


Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 50005
#define ll long long
using namespace std;
int n,m,Q[N];
ll S[N],G[N],f[N];
ll Squ(ll x)  {return x*x;}
ll ordi(int x)  {return f[x]+Squ(G[x])+2ll*(m+1)*G[x];}
double slope(int x,int y)  {return 1.0*(ordi(y)-ordi(x))/(G[y]-G[x]);}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1,x;i<=n;++i){
		scanf("%d",&x),S[i]=S[i-1]+x,G[i]=S[i]+i;
	}
	int l=0,r=0;
	for(int i=1;i<=n;++i){
		while(l<r&&slope(Q[l],Q[l+1])<=2*G[i])  l++;
		f[i]=f[Q[l]]+Squ(G[i]-G[Q[l]]-(m+1));
		while(l<r&&slope(Q[r-1],Q[r])>=slope(Q[r],i))  r--;
		Q[++r]=i;
	}
	printf("%lld\n",f[n]);
	return 0;
}
根据引用\[1\]和引用\[2\]的描述,题目中的影魔拥有n个灵魂,每个灵魂有一个战斗力ki。对于任意一对灵魂对i,j (i<j),如果不存在ks (i<s<j)大于ki或者kj,则会为影魔提供p1的攻击力。另一种情况是,如果存在一个位置k,满足ki<c<kj或者kj<c<ki,则会为影魔提供p2的攻击力。其他情况下的灵魂对不会为影魔提供攻击力。 根据引用\[3\]的描述,我们可以从左到右进行枚举。对于情况1,当扫到r\[i\]时,更新l\[i\]的贡献。对于情况2.1,当扫到l\[i\]时,更新区间\[i+1,r\[i\]-1\]的贡献。对于情况2.2,当扫到r\[i\]时,更新区间\[l\[i\]+1,i-1\]的贡献。 因此,对于给定的区间\[l,r\],我们可以根据上述方法计算出区间内所有下标二元组i,j (l<=i<j<=r)的贡献之和。 #### 引用[.reference_title] - *1* *3* [P3722 [AH2017/HNOI2017]影魔(树状数组)](https://blog.csdn.net/li_wen_zhuo/article/details/115446022)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [洛谷3722 AH2017/HNOI2017 影魔 线段树 单调栈](https://blog.csdn.net/forever_shi/article/details/119649910)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值