前缀和、滑动窗口机制

C市现在要转移一批罪犯到D市,C市有n名罪犯,按照入狱时间有顺序,另外每个罪犯有一个罪行值,值越大罪越重。现在为了方便管理,市长决定转移入狱时间连续的c名犯人,同时要求转移犯人的罪行值之和不超过t,问有多少种选择的方式(一组测试用例可能包含多组数据,请注意处理)?
在这里插入图片描述
这个题目可以先把连续的c个犯人的罪行值求出来,在对剩下的犯人进行滑动窗口机制
#include
#include
#include
using namespace std;
int main()
{
int n,t,c;
while(cin>>n>>t>>c)
{
int sum=0,cnt=0;
vector v(n);
for(int i=0;i<n;i++)
{
cin>>v[i];
if(i<c)
sum+=v[i];
}
if(sum<t)
cnt++;
for(int i=0;i<n-c;i++)
{
sum+=v[c+i]-v[i];//加上当前的,就要减去开始的,因为人数是确定的
if(sum<=t)
cnt++;
}
cout<<cnt<<endl;
}
}
关于前缀和的练习
https://blog.youkuaiyun.com/qq_37373425/article/details/70495712

### C++ 中滑动窗口算法的实现与解释 #### 概念介绍 滑动窗口是一种常用的优化技巧,特别适用于处理数组或字符串的一系列连续子序列问题。通过维护一个动态调整大小的窗口,在遍历过程中不断更新窗口内的状态,从而高效解决问题。 #### 时间复杂度特性 由于滑动窗口机制不会重复访问已经考察过的元素,因此整体的时间复杂度通常是线性的 O(n),而非嵌套循环带来的平方级别开销[^1]。 #### 应用场景举例 - **统计得分小于 K 的子数组数目**:利用前缀和配合二分查找快速定位满足条件的边界。 - **长度最小的子数组**:寻找第一个使得累积和达到目标值的位置,并在此基础上尝试收缩左侧边界以找到更短的有效区间。 - **最小覆盖子串**:采用双指针策略扩展右侧直至包含所有必需字符,随后逐步缩减左侧直到刚好失去合法性为止。 - **可见点的最大数目**:借助 map 或字典树结构记录角度范围内的障碍物分布情况。 - **最长合法子字符串的长度**:运用栈或者双向队列追踪当前有效括号配对关系及其极限位置。 #### 经典型题目解析 对于给定的任务——在一个固定宽度 `k` 下计算每轮移动后的局部极大/极小值: ```cpp class MaxMinSlidingWindow { public: vector<int> maxSlidingWindow(const vector<int>& nums, int k) { deque<int> dq; vector<int> result; for (int i = 0; i < nums.size(); ++i) { // 移除不在窗口范围内的索引 if (!dq.empty() && dq.front() == i - k) dq.pop_front(); // 移除所有比新加入元素小的项 while (!dq.empty() && nums[dq.back()] < nums[i]) dq.pop_back(); dq.push_back(i); // 当窗口形成后开始收集结果 if (i >= k - 1) result.push_back(nums[dq.front()]); } return result; } }; ``` 上述代码展示了如何使用双端队列(deque)来跟踪潜在的最大值候选者,确保每次迭代都能即时获取到最新的最大值而无需额外扫描整个窗口内部的内容[^3]。 #### 变种案例探讨 针对特定约束条件下(如允许翻转一定数量零值),可以通过引入计数器变量辅助判断何时应当扩张或收缩窗口边界,如下所示的例子即是在限定次数内最大化连续 '1' 的片段长度: ```cpp class Solution { public: int longestOnes(vector<int>& A, int K) { int left = 0, right = 0, zeros = 0, maxLength = 0; while (right < A.size()) { if (A[right++] == 0) ++zeros; // 超过可容忍限度则同步前进左右两端 while (zeros > K) if (A[left++] == 0) --zeros; maxLength = max(maxLength, right - left); } return maxLength; } }; ``` 这段程序巧妙地结合了贪心思想与滑动窗口框架,实现了高效的解决方案设计[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值