Atcoders [AGC049D] Convex Sequence 题解
AT_agc049_d [AGC049D] Convex Sequence
限制 不好满足,先不管它。限制 移项可得 ,即差分非严格单调递增,满足要求的序列为一个单谷序列。
我们考虑枚举最左侧的最小值的出现位置,先考虑在最左端的情况。
我们钦定序列最小值为 ,可以通过增加非最左侧的最小值的出现位置的元素的值来构造序列。具体的,我们每次选择一个区间 ,把这个区间的数从左到右依次增加 ,这样增量区间的差分不减,原序列的差分也非严格单调递增,构造出来的序列显然满足限制 。
接下来就是要证明所有满足要求的序列都可以由上述构造方式得到。这是易证的,钦定最小值之后,每一个合法的区间对应一个唯一的非严格单调递增的差分数组。注意到增量区间的差分实际上都是 ,每次操作后差分区间每个数加 。我们从右往左一位一位操作,每次对于位置 操作 直到满足差分数组的限制,注意到这种情况下构造不出来的条件为存在递减的差分,由限制 有差分非严格单调递增,矛盾,所以不会存在这种情况。
考虑到这种总和 的段只会有 个,我们直接把这些段预处理出来做容量为 的完全背包。这样,就满足了限制 。
注意到最小值可以不为 ,但每次最小值的增加伴随着 个元素一起增加,所以做背包的时候预处理出这种状态记为可行。
接下来考虑最左侧的最小值向右滑动。假设滑动前为 ,滑动后相当于背包里失去了 这个元素,增加 这个元素。注意到 的贡献与后缀 相同,不需要额外处理。由于统计方案数的背包是支持删除的,可以直接维护。
最后,再统计使最左侧的最小值向右滑动需要的操作的贡献即可,这同样是一个前缀,同上维护。
于是,我们得到了一个时间复杂度 的算法,空间复杂度 的优秀算法。
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探