Official
D - 蛍光ペンでマーキング / Highlighting with a Fluorescent Pen Editorial
by
D - 蛍光ペンでマーキング / Highlighting with a Fluorescent Pen Editorial
by
kyopro_friends
この問題は、俗に imos 法と呼ばれる、累積和に関連するテクニックを用いて解くことができます。
問題文の指示通り、愚直に各マスがマーキングされた回数の配列を更新する場合、1回あたり \(\Omega(W)\) 時間かかるため、 \(K\) 回の操作全体では \(\Omega(KW)\) 時間かかり、実行時間制限に間に合わせることは困難です。
ここで、各マスがマーキングされた回数の配列そのものではなく、その階差数列を保持することを考えます。
階差数列: 0 1 0 0 0 0 -1 0 0 ↓累積和 元の数列:0 0 1 1 1 1 1 0 0 0 ↑階差
1 回のマーキングで階差数列が変化する箇所は高々 2 箇所であるため、 \(O(K)\) 時間で答えの階差数列を得ることができます。最後に \(O(N)\) 時間掛けて累積和を取ることで答えを得ることができます。
実装例 (C++)
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, w, k;
cin >> n >> w >> k;
vector<int>count(n+1);
for(int i=0; i<k; i++){
int l;
cin >> l;
l--;
count[l]++;
count[l+w]--;
}
for(int i=0; i<n; i++){
count[i+1] += count[i];
}
for(int i=0; i<n; i++){
cout << count[i] << ' ';
}
}
実装例 (Python)
N, W, K = map(int, input().split())
count = [0] * (N+1)
for _ in range(K):
l = int(input())
l -= 1
count[l] += 1
count[l+W] -= 1
for i in range(N):
count[i+1] += count[i]
print(*count[:-1])
posted:
last update:
