Atcoders [AGC049D] Convex Sequence 题解

AT_agc049_d [AGC049D] Convex Sequence

限制 1 不好满足,先不管它。限制 2 移项可得 aiai1ai+1ai,即差分非严格单调递增,满足要求的序列为一个单谷序列。

我们考虑枚举最左侧的最小值的出现位置,先考虑在最左端的情况。

我们钦定序列最小值为 0,可以通过增加非最左侧的最小值的出现位置的元素的值来构造序列。具体的,我们每次选择一个区间 [i,n](i>1),把这个区间的数从左到右依次增加 1,2ni+1,这样增量区间的差分不减,原序列的差分也非严格单调递增,构造出来的序列显然满足限制 2

接下来就是要证明所有满足要求的序列都可以由上述构造方式得到。这是易证的,钦定最小值之后,每一个合法的区间对应一个唯一的非严格单调递增的差分数组。注意到增量区间的差分实际上都是 1,每次操作后差分区间每个数加 1。我们从右往左一位一位操作,每次对于位置 i 操作 [i,n] 直到满足差分数组的限制,注意到这种情况下构造不出来的条件为存在递减的差分,由限制 2 有差分非严格单调递增,矛盾,所以不会存在这种情况。

考虑到这种总和 m 的段只会有 O(m) 个,我们直接把这些段预处理出来做容量为 m 的完全背包。这样,就满足了限制 1

注意到最小值可以不为 0,但每次最小值的增加伴随着 n 个元素一起增加,所以做背包的时候预处理出这种状态记为可行。

接下来考虑最左侧的最小值向右滑动。假设滑动前为 i,滑动后相当于背包里失去了 [i+1,n] 这个元素,增加 [1,i1] 这个元素。注意到 [1,i1] 的贡献与后缀 [ni+2,n] 相同,不需要额外处理。由于统计方案数的背包是支持删除的,可以直接维护。

最后,再统计使最左侧的最小值向右滑动需要的操作的贡献即可,这同样是一个前缀,同上维护。

于是,我们得到了一个时间复杂度 O(mm) 的算法,空间复杂度 O(m) 的优秀算法。

#include <bits/stdc++.h>
using namespace std;
long long n,m,k=0,s[200000],f[200000],ans=0;
const long long mod=1e9+7;
int main()
{
	scanf("%lld%lld",&n,&m);
	while(s[k]<=m)k++,s[k]=s[k-1]+k;
	k--;
	for(int i=0;i<=m;i+=n)f[i]=1;
	for(int i=1;i<=min(k,n-1);i++)
	    for(int j=s[i];j<=m;j++)f[j]=(f[j]+f[j-s[i]])%mod;
	for(int i=1;i<=n;i++)
	    {
	    	if(i-1>k)break;
	    	ans=(ans+f[m-s[i-1]])%mod;
	    	for(int j=s[i];j<=m;j++)f[j]=(f[j]+f[j-s[i]])%mod;
	    	if(n-i<=k)for(int j=m;j>=s[n-i];j--)f[j]=(f[j]-f[j-s[n-i]])%mod;
		}
	printf("%lld\n",(ans%mod+mod)%mod);
	return 0;
} 
posted @   w9095  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示