구간합을 사용해서 이분탐색을 해도 되고 누적합을 사용해서 해당 위치에서 좌우로 얼마나 뻗을 수 있는지를 구해도 된다.


나는 이분탐색을 사용했다.


i : 0~n까지 차례대로 이분탐색을 한다.


i를 중심으로 좌우로 최대 얼마나 뻗을 수 있는지 이분탐색을 한 후


그 결과를 map에 저장한다(중요).


중요한 조건이 하나 있는데


--------------------------------------------------------------

i를 중심으로 좌우로 최대 mid만큼이 흥미로운 수열일 때


i를 중심으로 0~mid까지 모두 흥미로운 수열을 만족한다.

--------------------------------------------------------------


하지만 이걸 일일이 업데이트 시켜주면 시간초과가 난다.


그러므로 map에 {시작위치, 반지름} 형태로 저장시키고 만약 시작위치가 같다면 업데이트만 시켜주면 된다.


이렇게 하면 map에 듬성듬성 데이터가 들어가게 되는데


위에서 말했던 조건을 적절히 적용해야 한다.


간단한 예로


7 9

1

1

1

1

10

1

9


를 입력하면 map에


(0,2) (2,1) (5,1)이 들어가있다.


이걸로 결과를 일단 만들어 보면


4

0

2

0

0

2

0


이 나온다. 그리고 시작위치 0~2 사이에 1의 데이터가 비어있는데 조건에 따르면 0에서 반지름 2짜리 흥미로운 수열이 성립하므로


1에서는 [이전 위치에서 성립하는 흥미로운 수열의 반지름] - 1짜리는 무조건 성립하게 된다. 나머지 구간도 마찬가지로 적용할 수 있지만


흥미로운 수열의 길이가 -가 될 수는 없으므로 달라지는 것은 없다. 따라서


4

2

2

0

0

2

0


라는 결과가 나온다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
#include <cstring>
#include <map>
#include <algorithm>
using namespace std;
 
int n, s, a[100001];
map<intint> m;
 
void bis(int pivot) {
    int l = 0, r = min(n - pivot, pivot), mid = (l + r) / 2, ans = 0;
    while (l <= r) {
        mid = (l + r) / 2;
        int sl = a[pivot] - a[pivot - mid];
        int sr = a[pivot + mid] - a[pivot];
        if (sl > s || sr > s) r = mid - 1;
        else {
            ans = mid;
            l = mid + 1;
        }
    }
    if (!ans) return;
    if (m.count(pivot - ans)) 
        m[pivot - ans] = max(m[pivot - ans], ans);
    else 
        m.insert({ pivot - ans, ans });
}
 
int main() {
    scanf("%d%d"&n, &s);
    for (int i = 1; i <= n; i++) {
        scanf("%d"&a[i]);
        a[i] += a[i - 1];
    }
    for (int i = 1; i < n; i++
        bis(i);
    int prev = 0;
    auto it = m.begin();
    for (int i = 0; i < n; i++) {
        if (it == m.end()) {
            printf("%d\n", max(--prev, 0* 2);
            continue;
        }
        prev = max(prev - 10);
        if (i == (*it).first) 
            prev = max(prev, (*it++).second);
        printf("%d\n", prev * 2);
    }
    return 0;
}
cs


'BOJ' 카테고리의 다른 글

14950 정복자  (0) 2018.02.17
14949 외계 미생물  (0) 2018.02.17
14948 군대탈출하기  (0) 2017.12.14
14947 상자 배달  (0) 2017.12.14
14945 불장난  (0) 2017.12.12

+ Recent posts