环形数组上的滑动窗口,取模题型trick abc440_c C - Striped Horse

https://atcoder.jp/contests/abc440/tasks/abc440_c

思路:

1. 核心数学转化:从"下标"到"余数"

题目的涂色条件是:当 (i+x) mod 2W < W时,涂黑第 i 个方格。

我们可以将这个不等式理解为:对于一个固定的 x,凡是 i mod 2W 落在某个特定范围内的方格都会被涂黑。在一个周期 2W 内,满足条件的余数恰好有 W 个。由于 x 是可以自由选择的正整数,这 W 个余数在模 2W 的意义下是连续 的。 我们的目标是找到模 2W 的 2W 个余数中,连续的 W 个余数,使得这些余数对应的方格成本之和最小。

第一步:压缩(Mapping)
复制代码
vector<ll> a(n+1), vec(4*w);
rep(i,1,n) {
    cin>>a[i];
    vec[i%(2*w)]+=a[i]; // 将方格成本按余数分类累加
}
  • 方格数量 N 可能很大,但余数只有 2W 个。vec[r] 存储了所有满足 的方格之和。这一步将 的空间复杂度压缩到了
第二步:断环成链
复制代码
rep(i,2*w, 4*w-1) vec[i] = vec[i-2*w];
  • 因为余数是环状的(例如 的下一个余数是 0),为了方便处理"跨越边界"的连续区间,代码将 vec 数组复制了一份接在后面。这样,任何在环上连续的 W 个元素,在长度为 4W 的线性数组中都会表现为一段普通的连续区间。
第三步:滑动窗口
复制代码
ll ans=INF, tt=0;
ll l=0, r=-1;
while (r < 4*w) {
    while (r-l+1 < w) tt += vec[++r]; // 窗口不足 W,向右扩展
    ans = min(ans, tt);               // 更新当前窗口的最小和
    if (r == 4*w-1) break;
    tt -= vec[l++];                   // 窗口左端向右移,准备下一次滑动
}
  • 这是一个标准的双指针滑动窗口。窗口长度始终保持为 W。tt 维护当前窗口内余数成本的总和。遍历过程中,ans 会记录下所有可能的 W 长度区间中的最小值。

完整ac代码:

复制代码
void solve() {
    ll n,w;cin>>n>>w;
    vector<ll>a(n+1),vec(4*w);
    rep(i,1,n) {
        cin>>a[i];
        vec[i%(2*w)]+=a[i];
    }
    rep(i,2*w,4*w-1)vec[i]=vec[i-2*w];
    ll ans=INF,tt=0;
    ll l=0,r=-1;
    while (r<4*w) {
        while (r-l+1<w)tt+=vec[++r];
        ans=min(ans,tt);
        if (r==4*w-1)break;
        tt-=vec[l++];
    }
    cout<<ans<<endl;
}
相关推荐
量子炒饭大师11 小时前
【优化算法】滑动窗口的「义体化」重构 ——【滑动窗口】何为滑动窗口?滑动窗口算法的核心目的是什么?
c++·算法·重构·优化算法·双指针·滑动窗口
Tisfy1 天前
LeetCode 2540.最小公共值:双指针(O(m+n))
算法·leetcode·题解·双指针
handler014 天前
滑动窗口(同向双指针)算法:模板与例题解析
c语言·c++·笔记·算法·蓝桥杯·双指针·滑动窗口
量子炒饭大师11 天前
【优化算法】双指针算法的「义体化」重构 ——【双指针】双指针算法中的指针是如何定义的?如何使用它进行一些简单的算法?
c++·算法·重构·优化算法·双指针
量子炒饭大师14 天前
【优化算法:双指针算法刷题宝典】—— 三数之和
算法·优化算法·双指针·三数之和
qeen871 个月前
【算法笔记】双指针及其经典例题解析
c++·笔记·算法·双指针
李日灐1 个月前
【优选算法3】二分查找经典算法面试题
开发语言·c++·后端·算法·面试·二分查找·双指针
小肝一下1 个月前
每日两道力扣,day7
数据结构·c++·算法·leetcode·双指针·hot100·接雨水,四数之和
小肝一下1 个月前
每日两道力扣,day6
数据结构·c++·算法·leetcode·双指针·hot100
Byte不洛1 个月前
LeetCode双指针经典题
c++·算法·leetcode·双指针