ARC120 Swap2[python]

URL


https://atcoder.jp/contests/arc120/tasks/arc120_c

구속


2<= N<= 2*10^{5}
0<= A[i],B[i] <=10^{9}
입력한 값은 모두 정수입니다.

문제 개요

  • 길이 N의 수열 A, B가 있는데 아래의 조작을 반복하여 A를 B로 할 수 있는지 확인하고 필요한 최소 횟수
  • 를 구한다.
  • 작업:
  • 교체 A[i] 및 A[i+1]
  • A[i] 플러스 +1
  • A-1
  • 코드 커밋


    from collections import defaultdict
    n = int(input())
    a = list(map(int, input().split()))
    b = list(map(int, input().split()))
    a_ = [i+a[i] for i in range(n)]
    b_ = [i+b[i] for i in range(n)]
    if set(a_) != set(b_):
        print(-1)
        exit()
    dict_b = defaultdict(list)
    c = [0]*n
    for i in range(n):
        dict_b[b_[i]].append(i)
    # print(dict_b)
    a_count = {}  # a の要素に対して何回出てきたか
    for i in range(n):
        if a_[i] in a_count:
            a_count[a_[i]] += 1
        else:
            a_count[a_[i]] = 0
        #print(dict_b[a_[i]], a_count[a_[i]])
        c[i] = dict_b[a_[i]][a_count[a_[i]]]
    # c に関して転倒数の計算
    
    
    def mergecount(A):
        cnt = 0
        n = len(A)
        if n > 1:
            A1 = A[:n >> 1]
            A2 = A[n >> 1:]
            cnt += mergecount(A1)
            cnt += mergecount(A2)
            i1 = 0
            i2 = 0
            for i in range(n):
                if i2 == len(A2):
                    A[i] = A1[i1]
                    i1 += 1
                elif i1 == len(A1):
                    A[i] = A2[i2]
                    i2 += 1
                elif A1[i1] <= A2[i2]:
                    A[i] = A1[i1]
                    i1 += 1
                else:
                    A[i] = A2[i2]
                    i2 += 1
                    cnt += n//2 - i1
        return cnt
    
    
    print(mergecount(c))
    
    

    고찰하다.


    설명 AC
  • 자신의 고찰
  • 운영을 통해 전체 및 변경되지 않음
  • i, j 쌍이면 A[i]=A[i+j]+j, 이동
  • 모든 i에서 B[i]=A[i+j]+j를 반복적으로 찾을 수 있다면 A와 B를 일치시킬 수 있다
  • 일반적으로 하는 어떤 i에 대해 O(N)가 필요하기 때문에 계산량을 어떻게 줄입니까? =>끝
  • 설명
  • A_[i]=A[i]+i 변환된 정렬 A만들면B와 B가 같은 숫자의 집합이라면 일치할 수 있다
  • 작업에 관련된 최소 횟수는 A입니다.같은 숫자가 여러 개 있을 수 있음을 고려하지 않으면 A의 배열은 B의 배열 index로 바꾸면 인접 요소의 swap을 이용하여 배열을 바꾸는 작업이 된다. 이것은 밑으로 떨어지는 수량과 일치한다.
  • 넘어진 횟수: https://ja.wikipedia.org/wiki/엎어지다(수학)
  • 예: A=[1,4,5,3,2] B = [3,4,5,1,2]시, B에 따른 index,A]사전{1:4,2:5,3:1,4:2,5:3}처럼 바꾸면 AB의 조작을 [4,2,3,1,5]와 인접한 swap을 통해sort를 진행하는 것과 같게 하기
  • 여기는 A 입니다.동일한 숫자가 여러 개 있을 때 어떤 조작이 최소인지를 고려하면 이전부터 탐욕에 가장 가까운 동일한 숫자로 변경됐음을 알 수 있다.
  • 증명: $A[i] = A_[j]=B[k]=B[l] i, j, k, l($i보다 크다.
  • 실시 방침

  • A_,B_ 의 배열
  • B_앞에서 스캔을 시작하면 사전dict는 현재 나타난 숫자를 키로 하고 몇 번 출현한 것을 요소로 한다b의 O (N) 만들기
  • 이때defaultdict를 통해 목록을 사전에 삽입하면 한 키에 여러 값을 관리할 수 있다
  • dict_b 기초, AC로 변환 O(N)
  • dict관리를 통해 현재 여러 요소에 대응하는 어떤 값이 몇 번이나 나타났는지
  • C 계산 밑의 O(NlogN)
  • 다음의 반성

  • A[i]=A[i+j]+j에서 A[i]=A[i]+i 변환이 잦기 때문에 스스로 알아차리고 싶다
  • 꼴찌에 관해서는 창고도 없고 풀 수 없어도 어쩔 수 없지만 이름과 개요를 들어봤는데 경기에서 욕을 먹었으면 좋겠다
  • 넘어지는 횟수를 이해하는 알고리즘
  • 참고 자료


    공식 해설https://atcoder.jp/contests/arc120/editorial/1921
    밑으로 떨어지는 알고리즘https://kira000.hatenadiary.jp/entry/2019/02/23/053917
    python 사전에 목록을 입력하십시오 https://www.haya-programming.com/entry/2018/04/24/002524
    여기서 카운트다운 라이브러리 빌리기https://nagiss.hateblo.jp/entry/2019/07/01/185421

    좋은 웹페이지 즐겨찾기