尺取法产生变化的滑动窗口, 同向扫描。
给一个长度为 的数组 和一个数 , 找一个长度最小的连续的区间, 使其区间和等于 。
思路
若枚举所有长度的区间, 是 复杂度。
可以用尺取法:
假设所有数都是正整数, 对于区间 , 设其区间和为 , 当 时, 令 , 同时 。 若 时, 令 , 同时 。如果 , 则 , 且置 。
因为找的区间时连续的, 因此如果 当前的 区间和 , 那么后续的 都会 。因此, 若想找的是 的区间, 必须抛弃掉 。
那么假如有负数呢?很好办, 定义 为序列中最小的负数, 然后对所有数 , 即做一个偏移, 让所有数都为整数, 因此可以证明包含负数情况跟正整数情况相同。
是 的最小区间
题目:https://vjudge.csgrandeur.cn/problem/POJ-3061#author=rainty7
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
LL a[N];
LL q[N], f[N];
void solve() {
LL n,m;
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i];
LL sum = a[1], res = 0x3f3f3f3f;
LL i = 1, j = 1;
while(j <= n)
{
//cout << i << " " << j << " " << sum << endl;
if(sum >= m)
{
res = min(j - i + 1, res);
sum -= a[i];
i++;
if(i > j) {sum = a[i], j++;}
}
if(sum < m) {j++;sum += a[j];}
}
if(res >= 0x3f3f3f3f / 2) cout << 0 << endl;
else
cout << res << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--)
solve();
return 0;
}
区间和绝对值与t之差最小
https://vjudge.csgrandeur.cn/problem/POJ-2566#author=CCUT_1816
```asd