C - センサーデータの異常検知 / Anomaly Detection in Sensor Data Editorial by admin
Gemini 3.0 FlashOverview
This problem asks you to find the number of contiguous subarrays of length \(K\) within a sequence of length \(N\) whose sum is \(0\) or less.
Analysis
First, let’s consider a naive (brute-force) approach. For each starting position \(i\) (\(1 \leq i \leq N-K+1\)), we compute the sum of the \(K\) elements starting from that position and check whether it is \(0\) or less.
However, this method takes \(O(K)\) time to compute the sum of a single subarray. Since there are approximately \(N\) subarrays, the overall time complexity is \(O(N \times K)\). Given the constraints of this problem where \(N, K \leq 2 \times 10^5\), \(N \times K\) can reach up to \(4 \times 10^{10}\), which will not finish within the typical time limit (around 2 seconds).
Therefore, we focus on the key observation that “the sums of adjacent subarrays share most of their elements.”
For example, with \(N=5, K=3\) and sequence \(A = [A_1, A_2, A_3, A_4, A_5]\): 1. First subarray: \((A_1 + A_2 + A_3)\) 2. Next subarray: \((A_2 + A_3 + A_4)\)
Comparing these two, we can see that recomputing the common part \((A_2 + A_3)\) repeatedly is wasteful. The second sum can be obtained from the first sum by simply subtracting \(A_1\) and adding \(A_4\).
Algorithm
This technique is called the sliding window method.
- First, compute the sum
current_sumof the first subarray (from the \(1\)-st to the \(K\)-th element). - If
current_sumis \(0\) or less, increment the count by \(+1\). - Next, slide the window one position to the right at a time.
- Subtract the element leaving the window (left end) from
current_sum. - Add the element entering the window (right end) to
current_sum. - If the updated
current_sumis \(0\) or less, increment the count by \(+1\).
- Subtract the element leaving the window (left end) from
- Repeat this until the end.
With this method, each step requires only “one subtraction and one addition,” making it very efficient.
Complexity
- Time complexity: \(O(N)\)
- Reading the data takes \(O(N)\), and the sliding window scan takes \(O(N)\), so the overall complexity is \(O(N)\). This is fast enough even when \(N=2 \times 10^5\).
- Space complexity: \(O(N)\)
- \(O(N)\) memory is used to store the input sequence.
Implementation Notes
Data input: Since \(N\) and the values of \(A_i\) can be large, it is faster to read all input at once using something like
sys.stdin.read().split()rather than calling Python’sinput()multiple times.Updating the sum: You need to correctly specify the indices of the element entering and leaving the window, as in
current_sum += a[i + k] - a[i].Initializing the count: Don’t forget to check the sum of the first \(K\) elements before the loop begins.
Source Code
import sys
def solve():
# 標準入力からすべてのデータを取得し、空白で分割します
input_data = sys.stdin.read().split()
if not input_data:
return
# N(データ数)とK(連続時間数)を取得します
n = int(input_data[0])
k = int(input_data[1])
# 各時間の品質指標を整数のリストとして取得します
# map関数を使用することで、大量のデータを効率的に変換します
a = list(map(int, input_data[2:]))
# 最初のK時間の合計(最初のウィンドウ)を計算します
current_sum = sum(a[:k])
# 異常期間の個数をカウントする変数
count = 0
# 最初のウィンドウが異常期間(合計が0以下)であるか判定します
if current_sum <= 0:
count += 1
# スライディングウィンドウを用いて、2番目以降のウィンドウの合計を効率的に計算します
# i はウィンドウから外れる要素のインデックス、i + k は新しく入る要素のインデックスです
for i in range(n - k):
# 前の合計から外れる要素を引き、新しい要素を加えることで次の合計を求めます
current_sum += a[i + k] - a[i]
# 合計が0以下であれば異常期間としてカウントします
if current_sum <= 0:
count += 1
# 結果を出力します
print(count)
if __name__ == '__main__':
solve()
This editorial was generated by gemini-3-flash-preview.
posted:
last update: