-
363-B, *1100코드포스 2021. 7. 22. 21:27
Problem - 363B - Codeforces
codeforces.com
문제
- n(1≤n≤1.5⋅105)개의 수가 나열되어 있다
- 연속된 k개의 수의 합이 가장 작은부분은 어디인가?
- O(nlog n) 정도 알고즘은 통과할 수 있다
O(n)
누적합을 저장하는 배열(acc)을 만들면 O(n)
acc[i]−acc[i−k]
을 이용하여 i−k+1부터 i까지 원소의 합을 구할 수 있다
이제 모든 경우에 대해 값을 비교하여 최솟값을 구한다 O(n−k)1234567891011121314151617181920212223242526272829303132333435#include <bits/stdc++.h>#define endl "\n"using namespace std;int h[200000];int acc[200000];int main(){ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int n, k;int tmp;cin >> n >> k;for(int i = 1; i <= n; i++) cin >> h[i];acc[1] = h[1];for(int i = 2; i <= n; i++) acc[i] = acc[i-1] + h[i];int minval = 20000000;int minval_ind = 1;for(int i = k; i <= n; i++) {if(minval > acc[i]-acc[i-k]){minval = acc[i]-acc[i-k];minval_ind = i-k+1;}}cout << minval_ind << endl;return 0;}csO(n−k)
s를 배열a 앞에서부터 k개의 수의 합이라 하자
s=k∑i=1ai
s에 a[k+1]를 더하고 a[1]을 빼면 2번째 수부터 k+1번째 수까지의 합을 구할 수 있다 O(1)
다시 s에 a[k+2]를 더하고 a[2]을 빼면 3번째 수부터 k+2번째 수까지의 합을 구할 수 있다 O(1)
같은방법으로 n−k번 반복한다 O(n−k)123456789101112131415161718192021222324252627282930#include <bits/stdc++.h>#define endl "\n"using namespace std;int arr[200000] {};int main(){ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int n, k;cin >> n >> k;for(int i = 1; i <= n; i++) cin >> arr[i];int s = accumulate(arr+1, arr+k+1, 0);int minval = s;int minval_ind = 1;for(int i = 1; i <= n-k; i++){s = s + arr[i+k] - arr[i];if(s < minval){minval = s;minval_ind = i+1;}}cout << minval_ind << endl;return 0;}cs시간초과
배열(a)의 앞에서부터 매번 k개의 원소를 더한 값을 비교하는 brute force 를 시행하는 경우를 보자
a[i]+a[i+1]+⋅⋅⋅+a[i+k−1]i=0,1,2,⋅⋅⋅,n−k
더하는데 k번의 연산이 필요하고, n−k번 비교를 하므로
O(k(n−k))의 수행시간이 드는데 n=1.5⋅105, k=n/2 이면
대략 5.6⋅109 번 연산을 하므로 시간초과이다'코드포스' 카테고리의 다른 글
456-A, *1100 (0) 2021.07.23 519-B, *1100 (0) 2021.07.23 270-A, *1100 (0) 2021.07.22 706-B, *1100 (0) 2021.07.22 158-B, *1100 (0) 2021.07.21