ABOUT ME

Today
Yesterday
Total
  • [ABC038 C] 単調増加
    문제 풀이/AtCoder 2023. 1. 30. 16:35

    난이도: 894 // 실험적

     

    번역

    더보기

    N개의 정수가 주어집니다. i번째 수는 ai입니다.

    lr이면서 al,al+1,,ar이 증가수열이 되도록 하는 (l,r)의 개수를 찾으세요.

    즉, li<r인 모든 i에 대해 ai<ai+1를 만족시키는 (l,r)의 개수를 찾으세요.

     

    태그

    더보기
    • Sweeping (스위핑)

     

    풀이

    1. l을 고정시킬 때, 가능한 개수는?

    더보기

    조건의 특성상, r1<r2이고 (l,r2)가 증가수열이었다면, (l,r1)도 증가수열이 됩니다.

    또한, r1<r2이고 (l,r1)이 증가수열이 아니라면, (l,r2)도 증가수열이 아니게 됩니다.

     

    이제, rl에서부터 시작해서 오른쪽으로 한 칸씩 이동해봅시다.

    그럼, rarar+1을 만나게 되거나, N번째 수까지 이동하게 됩니다.

     

    r이 멈추게 되면, 어떤 특정한 l에 대해 증가수열을 만들게 되는 r의 끝점을 알게 되고,

    시작점은 자명히 r=l일테니, 가능한 경우는 rl+1가지가 됨을 알 수 있습니다.

     

    2. 더 빠르게 구해보기

    더보기

    (1번)의 방식대로만 돌리면, O(N2)의 시간이 나오게 됩니다.

    하지만, lN부터 한 칸씩 왼쪽으로 이동시키면, 이로 인한 r의 위치는 아래 둘 중 하나로 고정됩니다.

    • al<al+1: r의 위치에 변함이 없습니다. al<al+1 다음의 비교는 l+1에서 한 비교와 동일할테니까요.
    • alal+1: r의 끝점이 l로 이동합니다. 첫 비교부터 증가수열이 아니라는 결론이 나왔으니까요.

     

    다르게 말하자면, lN에서부터 왼쪽으로 이동시키면, 새로운 r의 위치를 O(1)에 계산할 수 있게 됩니다.

     

    코드

    더보기
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int arr[100020];
     
    void Main(){
        int n; cin >> n;
        for (int i = 1; i <= n; i++){ cin >> arr[i]; }
        ll ans = 0;
        int lst = n; for (int i = n; i >= 1; i--){
            if (arr[i] >= arr[i+1]){ lst = i; }
            ans += lst-i+1;
        }
        cout << ans;
    }
    cs

    '문제 풀이 > AtCoder' 카테고리의 다른 글

    [ABC006 D] トランプ挿入ソート  (0) 2023.01.30
    [ABC213 E] Stronger Takahashi  (0) 2023.01.30
    [ABC226 C] Martial artist  (0) 2023.01.30
    [AGC030 A] Poisonous Cookies  (0) 2023.01.30
    [ARC119 A] 119 × 2^23 + 1  (0) 2023.01.30
Designed by Tistory.