만드는 중입니다

아직 만드는 중이라 바뀔 수 있습니다

Mo 알고리즘 최적화

시간 제한1초메모리 제한1024 MB

요약
배열의 구간 합 질의 Q개의 순서를 바꿔서 주어진 포인터 이동 코드의 이동 횟수가 최소가 되도록 출력합니다.
난이도

보통10점 중 6점

유형
정렬, 슬라이딩 윈도우, 누적 합
정답자
아직 제출이 없습니다

문제

Juku는 특별히 중요한 올림피아드를 준비하다가 다음 문제를 발견했다.

배열의 구간 합

길이가 NN인 배열 AA와 (l,r)(l, r) 형태의 쿼리 QQ개가 주어진다.

각 쿼리마다 A\[l]+A\[l+1]+⋯+A\[r]A\[l] + A\[l + 1] + \cdots + A\[r]의 값을 답으로 출력한다.

N=Q=105N = Q = 10^5임이 알려져 있다.

Juku는 이 문제를 풀기 위해 다음 의사코드를 작성했다.

lptr = 1, rptr = 1, sum = A[1], ops = 0

for each query (ql, qr):
    while rptr < qr:
        rptr += 1
        sum += A[rptr]
        ops += 1
    while lptr > ql:
        lptr -= 1
        sum += A[lptr]
        ops += 1
    while rptr > qr:
        sum -= A[rptr]
        rptr -= 1
        ops += 1
    while lptr < ql:
        sum -= A[lptr]
        lptr += 1
        ops += 1
    print sum

이 코드의 실행 시간이 제한 시간을 넘었다. 그러나 Juku는 어느 강의에서 "Mo's algorithm"이라는 이야기를 들은 기억이 어렴풋이 났고, 이렇게 생각하기 시작했다. 쿼리의 순서를 바꾸면 프로그램이 제한 시간 안에 들어갈 수 있을까? 그리고 쿼리 순서만 바꿔서 프로그램을 얼마나 빠르게 만들 수 있을까?

QQ개의 쿼리 (l,r)(l, r)이 주어진다. 쿼리는 균등 분포를 따른다고 보장된다(힌트의 참고 사항 참조). 위 의사코드를 실행한 뒤 ops의 최종 값이 최대한 작아지도록 쿼리를 재배열하라.

입력

첫 줄에 공백으로 구분된 두 정수 NN과 QQ가 주어진다(N=Q=105N = Q = 10^5). 이어지는 QQ개의 줄에는 각각 공백으로 구분된 두 정수 ll과 rr이 주어진다(1≤l≤r≤N1 \le l \le r \le N).

출력

QQ개의 줄을 출력한다. 각 줄에는 공백으로 구분된 두 정수 ll과 rr을 출력한다. 출력하는 쿼리는 입력 쿼리들의 순열이어야 한다.

힌트

실제 입력 파일은 다음 코드로 생성되었다.

print(100000, 100000)
for i in 1...100000:
    l = random(1, 100000)
    r = random(1, 100000)
    if (l < r):
        print(l, r)
    else:
        print(r, l)

여기서 random(1, 100000)은 1≤x≤100 0001 \le x \le 100\,000을 만족하는 정수 xx를 반환하며, 가능한 반환값은 모두 같은 확률로 나온다.

예제1

  1. 예제 1

    입력
    7 6
    1 5
    2 7
    4 4
    1 2
    3 6
    1 2
    
    예상 출력
    2 7
    1 2
    3 6
    1 2
    4 4
    1 5