【Atcoder】 [AGC040E] Prefix Suffix Addition

题目链接

Atcoder方向
Luogu方向

题目解法

参考多篇题解
考虑可以将 a i a_i ai 拆分成 b i b_i bi c i c_i ci b i b_i bi 是由开头的不降子序列覆盖到的, c i c_i ci 是由结尾的不升子序列(从结尾往前不降相当于从前往后的不升)覆盖到的
考虑一个结论是:最少的操作次数为 ∑ [ b i > b i + 1 ] + ∑ [ c i < c i + 1 ] + 2 ? \sum[b_i>b_{i+1}]+\sum [c_i<c_{i+1}]+2? [bi>bi+1]+[ci<ci+1]+2?,可能常数什么的需要分类讨论一下,但整体的框架是这样的
考虑一个 d p dp dp,令 d p i , j dp_{i,j} dpi,j 为第 i i i 位填 j j j 的最小操作次数
d p i , j = min ⁡ { d p i − 1 , k + [ j < k ] + [ a i − j > a i − 1 − k ] } dp_{i,j}=\min\{dp_{i-1,k}+[j<k]+[a_i-j>a_{i-1}-k]\} dpi,j=min{dpi1,k+[j<k]+[aij>ai1k]}
稍微移一下项:
d p i , j = min ⁡ { d p i − 1 , k + [ j < k ] + [ j < a i − a i − 1 + k ] } dp_{i,j}=\min\{dp_{i-1,k}+[j<k]+[j<a_i-a_{i-1}+k]\} dpi,j=min{dpi1,k+[j<k]+[j<aiai1+k]}
考虑对于相同的 i i i d p i , j dp_{i,j} dpi,j 一定只有至多 3 3 3 种连续不同值,原因是考虑 j j j 越小, d p i , j dp_{i,j} dpi,j 一定越大,且判断只有 2 2 2
令值分别为 d , d + 1 , d + 2 d,d+1,d+2 d,d+1,d+2
考虑三段的划分,这里令 [ 0 , p ] = d + 2 [0,p]=d+2 [0,p]=d+2 [ p + 1 , q ] = d + 1 [p+1,q]=d+1 [p+1,q]=d+1 [ q + 1 , a i ] = d [q+1,a_i]=d [q+1,ai]=d
考虑 d p dp dp 转移式的变化(为了与题解保持一致 方便,令 D = a i − a i − 1 D=a_i-a_{i-1} D=aiai1
从段 1 1 1 转移(值为 d + 2 d+2 d+2): d p i , j = d + 2 + [ j < 0 ] + [ j < D ] = d + [ j < D ] dp_{i,j}=d+2+[j<0]+[j<D]=d+[j<D] dpi,j=d+2+[j<0]+[j<D]=d+[j<D]
从段 2 2 2 转移(值为 d + 1 d+1 d+1): d p i , j = d + 1 + [ j < p + 1 ] + [ j < D + p + 1 ] dp_{i,j}=d+1+[j<p+1]+[j<D+p+1] dpi,j=d+1+[j<p+1]+[j<D+p+1]
从段 3 3 3 转移(值为 d d d): d p i , j = d + [ j < q + 1 ] + [ j < D + q + 1 ] dp_{i,j}=d+[j<q+1]+[j<D+q+1] dpi,j=d+[j<q+1]+[j<D+q+1]
考虑对 D D D 的正负性分类讨论,因为这会影响新的 p , q p,q p,q 范围

  1. D ≥ 0 D\ge 0 D0,自己手画图可以发现,
    [ 0 , m i n ( q , d + P ) ] [0,min(q,d+P)] [0,min(q,d+P)],最小值为 d + 2 d+2 d+2
    [ m i n ( q , d + P ) + 1 , D + q ] [min(q,d+P)+1,D+q] [min(q,d+P)+1,D+q],最小值为 d + 1 d+1 d+1
    [ D + q + 1 , a i ] [D+q+1,a_i] [D+q+1,ai],最小值为 d d d
    因为 q < a i − 1 q<a_{i-1} q<ai1 所以这里不需要考虑 D + q + 1 ≥ a i D+q+1\ge a_i D+q+1ai 的情况
  2. D < 0 D<0 D<0,同理,直接给出结论
    [ 0 , m i n ( p , D + q ) ] [0,min(p,D+q)] [0,min(p,D+q)],最小值为 d + 2 d+2 d+2
    [ m i n ( p , D + q ) + 1 , q ] [min(p,D+q)+1,q] [min(p,D+q)+1,q],最小值为 d + 1 d+1 d+1
    [ q + 1 , a i ] [q+1,a_i] [q+1,ai],最小值为 d d d
    注意如果 m i n ( p , D + q ) < 0 min(p,D+q)<0 min(p,D+q)<0 的话,需要让 n e w p = − 1 newp=-1 newp=1,因为我们维护的是 d d d 的值,这个值是第三段的,所以一切以第三段为准
    如果 q + 1 ≥ a i q+1\ge a_i q+1ai,那么第三段为空,所以 d + 1 d+1 d+1,而第三段的区间变成第二段,第二段变成第一段,第一段为空

注意要运行到 n + 1 n+1 n+1,这时一定只有第三段,所以答案为 d d d
时间复杂度 O ( n ) O(n) O(n)

#include <bits/stdc++.h>
using namespace std;
const int N=200100;
int n,a[N];
inline int read(){
	int FF=0,RR=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
	for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
	return FF*RR;
}
int main(){
	n=read();
	for(int i=1;i<=n;i++) a[i]=read();
	int p=-1,q=-1,d=0;
	//第一段[0,p]
	//第二段[p+1,q]
	//第三段[q+1,a_i]
	for(int i=1;i<=n+1;i++){
		int D=a[i]-a[i-1];
		if(D>=0){
			//[0,min(q+1,D+p+1)) d+2
			//[min(q+1,D+p+1),D+q] d+1
			//[D+q+1,a_i] d
			int tp=p,tq=q;
			p=min(tq,D+tp),q=D+tq;
			//D+tq=a[i]-a[i-1]+tq<=a[i]
		}
		else{
			//[0,min(p+1,D+q+1)) d+2
			//[min(p+1),D+q+1,q] d+1
			//[q+1.a_i] d
			int tp=p,tq=q;
			p=min(tp,D+tq),q=tq;
			//第一段不存在,则p=-1
			if(p<0) p=-1;
			//第三段不存在,需要把第三段去掉,且第一段->第二段,第二段->第三段,第一段为空
			if(q>=a[i]) q=p,p=-1,d++;
		}
	}
    // if(q+1>a[n]) d++;
	printf("%d",d);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值