环形数组上的滑动窗口,取模题型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;
}
相关推荐
老鼠只爱大米1 天前
LeetCode算法题详解 42:接雨水
leetcode·动态规划·双指针·单调栈·接雨水·雨水收集
老鼠只爱大米1 天前
LeetCode算法题详解 11:盛最多水的容器
leetcode·面试题·双指针·盛最多水的容器·面积最大化
老鼠只爱大米3 天前
LeetCode算法题详解 15:三数之和
算法·leetcode·双指针·三数之和·分治法·three sum
老鼠只爱大米3 天前
LeetCode算法题详解 283:移动零
算法·leetcode·双指针·快慢指针·移动零·move zeroes
田梓燊4 天前
leetcode 有序数组的平方
双指针
无尽的罚坐人生6 天前
hot 100 42. 接雨水
数据结构·算法·leetcode·动态规划··双指针
羑悻的小杀马特6 天前
LeetCode 42接雨水全解:暴力超时→DP降维打击→双指针极限压缩空间→单调栈栈式凹槽定位,全景式解析算法优化路径
算法·leetcode·职场和发展·动态规划·双指针·单调栈·接雨水
无尽的罚坐人生10 天前
hot 100 283. 移动零
数据结构·算法·双指针
伟大的车尔尼10 天前
双指针题目:K 和数对的最大数目
双指针·哈希表