koistudy 지역본선 2차모의고사 풀이집
TRANSCRIPT
모의고사
13003 HYEA
사랑의 짝대기
M 번 사랑의 짝대기를 타자(Subtask 1: 단순 구현 ; 2, 3: 그래프 이론 )
사랑의 짝대기 (33 점 )
모든 사람은 서로 다른 사람을 가리킨다 .
가리킨 사람을 계속 가리키다 보면 언젠간 다시 재현이로 돌아온다 .
M 을 재현이가 방문된 횟수로 나눈 나머지만큼만 가면 된다 .
예제의 경우에는 1->3->4->1 같이 길이 3 의 회로가 생기기 때문에 100 을 3 으로 나눈 나머지인 1 번만 가보면 된다 .
사랑의 짝대기 (33 점 )
M 번 사랑의 짝대기를 타고 간다 .
사랑의 짝대기로 가리킨 사람이 있는 배열이 A 라고 하고 , 현재 가리킨 사람이 p 라고 하면
p=A[p]
를 M 번 반복하는 것으로 답을 이끌어낼 수 있다 .
사랑의 짝대기 (100 점 )
경로를 타고 가다가 cycle 로 가게 된다 .
경로를 타고 가다가 cycle 이 확인되면 M 을 cycle 의 경로길이로 나눈 나머지로 처리를 해준다 . 구현은 소스코드를 참고하길 바란다 .
사과의 그림판
그림판을 채우자(Subtask 1: Flood fill; Subtask 2: 좌표 압축 )
사과의 그림판 (75 점 )
입력 받기 : 문자열이나 문자가 쿼리에 들어오면 %s 로 문자열 꼴로 받은 후에 앞 문자를 확인하는 게 좋다 . 자세한 구현은 소스코드를 참고하기 바란다 .
사과의 그림판 (75 점 )
Flood fill: 그림 판을 채우는 것 처럼 , 자기자신과 같으나 인접한 칸들을 채우는 방식이다 .
자신의 상하좌우 칸을 DFS 를 ( 재귀호출로 구현 ) 사용해서 같은 색으로 칠해나갈 수 있다 .
꼭 코딩 해보기를 바란다 . ( 작년 , 제작년에 Flood Fill 이 나왔음 )
사과의 그림판 (75 점 )
int dx[4]={-1,0,1,0};int dy[4]={0,1,0,-1}; // 상하좌우 좌표를 다음과 같은 방식으로 표현한다 .void dfs(int a,int b,int c,int d){ if(board[a][b]!=d) return; // 현재 색이 원래 판 색과 같지 않으면 끝낸다 . board[a][b]=c; // 현재 색을 채운다 . for(int i=0;i<4;i++) dfs(a+dx[i],b+dy[i],c); // 상하좌우에 대해 반복한다 . return;}
DFS 의 구현에는 다양한 방법이 있다 . 이 방법은 경계를 -1 의 색으로 칠해놓아서 경계로 나가지 못하는 방법이다 . a, b 의 범위를 직접 확인할 수도 있다 .
사과의 그림판 (100 점 )
좌표압축을 하면 된다 . 좌표압축이란 실제 중요한 좌표들은 색을 칠할 좌표들이라는 것을 이용 ,
필요 없는 좌표들을 모두 없애는 작업이다 .
STL 중에 unique 란 STL 은 unique(a.begin(),a.end()) 를 하면 연속으로 중복된 원소를 제거해 주고 , 마지막 원소 다음 원소의 it-erator(pointer 같은 개념 ) 을 제공한다 .
좌표압축을 한 후에 flood fill 을 하면 된다 .
사과의 그림판 (100 점 )
좌표압축의 방법은 X 좌표를 배열 a 에 넣고 정렬을 한 후
X[i]=lower_bound(a.begin(), a.end(), x[i]);
의 방법을 사용한다 . 1 의 개수를 셀 때는 a[i+1]-a[i] 가 길이인 점을 이용한다 .
화분
너비 W 안에 있는
최대값과 최소값의 차가 D 이상
이 되게 하는 최소의 W 를 찾아라(Subtask 1: Greedy, Subtask 2: Sliding Window)
(koosaga: RMQ, parametric (? ????) )
화분 (45 점 )
최솟값과 최댓값은 가장 끝에 위치할 때가 답이다 . 양끝에 최솟값과 최댓값이 아니라면 , 그 구간으로 답을 축소할 수 있다 .
최솟값과 최댓값의 차이가 D 이상이면 너비를 갱신해 준다 .
구현이 간단하다 .
화분 (100 점 )
어차피 연속된 구간만 구해야 한다 . 구간을 연속적으로 훑자 !
Sliding Window: 어떤 구간의 왼쪽 제한과 오른쪽 제한을 번갈아 오른쪽으로 이동해 가며 구간에 대해 보는 방식 . Double pointer 라는 테크닉으로도 부른다 .
화분 (100 점 )
화분 문제에서는 사용되는 중요한 함수 ( 쿼리 ) 세 가지가 있다 .
어떤 길이 N 의 배열에 대해서 , 아무것도 없는 [0,0) 의 구간에서 시작해
현재 구간의 최댓값을 구한다 .
구간을 오른쪽으로 한 칸 늘린다 .
구간의 왼쪽을 한 칸 줄인다 .
화분 (100 점 )
이 아이디어에서는
답이 될 수 있는 칸들을 사용해서
모두 상수시간 안에 쿼리를 처리한다 .
화분 (100 점 )
3 1 4 1 5 9 2 6 5 3
화분 (100 점 )
3 1 4 1 5 9 2 6 5 3
설명 : 3 은 답이 될 수 있는 수이다 .
화분 (100 점 )
3 1 4 1 5 9 2 6 5 3
설명 : 1 은 답이 될 수 있는 수이다 . 구간이 왼쪽으로 한 칸 축소되면 1 이 답이다 .
화분 (100 점 )
3 1 4 1 5 9 2 6 5 3
설명 : 4 가 구간에서 제외되려면 3 과 1 이 제외되어야 하므로 , 3 과 1 은 절대 답이 될 수 없다 . 그러므로 4 가 답의 유일한 후보이다 .
화분 (100 점 )
3 1 4 1 5 9 2 6 5 3
설명 : 왼쪽에서 수 3 개가 제외되면 1 이 답이 될 수 있다 .
화분 (100 점 )
3 1 4 1 5 9 2 6 5 3
설명 : 같은 방법으로 후보를 구하면 9 와 6 이라는 것을 알 수 있다 . 여기서 중요한 고찰을 할 수 있다 .
화분 (100 점 )
후보인 수들은 오른쪽에자기보다 큰 수가 없다 .
화분 (100 점 )
3 1 4 1 5 9 2 6 5 3
설명 : 제거는 간단하다 . 왼쪽에서 제거 할 때 , 제거하는 수가 수의 후보라면 단순히 후보에서 삭제해주는 것으로 충분하다 . 그 수는 다시 볼 일이 없다 .
화분 (100 점 )
이런 자료구조를 deque 를 사용해서 만들 수 있다 .
deque 란 stack 과 queue 를 합쳐놓은 자료구조로
배열의 왼쪽과 오른쪽에
상수시간에 삽입삭제가 가능한 자료구조 이다 . (double-ended queue, deck 이라고 발음한다 .)
화분 (100 점 )
deque 는 STL( 표준 라이브러리 ) 를 이용해서 쓸 수 있다 .
deque 는 표준 헤더 queue 에 정의되어 있다 .
deque 에는 다음과 같은 함수들이 있다 .
화분 (100 점 )
#include<queue>
std::deque<int> DQ;
DQ.push_front(a); //DQ 의 앞쪽에 a 를 넣는다 .
DQ.push_back(a); //DQ 의 뒤쪽에 a 를 넣는다 .
DQ.empty(); //DQ 가 비어있으면 true, 아니면 false 를 반환한다 .
DQ.size(); //DQ 에 들어있는 원소의 수를 반환한다 .
DQ.front(); //DQ 에 가장 앞쪽에 있는 수를 확인한다 .
DQ.pop(); //DQ 에 가장 뒤쪽에 있는 수를 반환한다 .
화분 (100 점 )
#include<queue>
std::deque<int> DQ; //DQ 의 구조 > []
DQ.empty(); // DQ 가 비어있으므로 true 를 반환한다 .
DQ.push_front(3); //DQ 의 구조 > [3]
DQ.back();// 가장 뒤쪽에 있는 수는 3 이므로 3 을 반환한다 .
DQ.push_back(7); //DQ 의 구조 > [3, 7]
DQ.push_front(9); //DQ 의 구조 > [9, 3, 7]
DQ.front(); // 가장 앞쪽에 있는 수는 9 이므로 9 를 반환한다 .
DQ.back(); // 가장 뒤쪽에 있는 수는 7 이므로 7 을 반환한다 .
DQ.size(); //DQ 의 원소가 3 개이므로 3 을 반환한다 .
DQ.pop_back(); DQ.pop_back(); // [9, 3, 7]-> [9, 3] -> [9] 순으로 제외된다 .
화분 (100 점 )
DQ 를 사용해서 , 쿼리를 처리할 때 새로운 원소가 들어오면 , 그 원소보다 큰 원소가 발견될 때 까지 뒤에서 뺀 후 , 그 원소를 뒤에 삽입하면 된다 .
DQ 를 사용해서 , 쿼리를 처리할 때 , 원소가 제거되면 , 그 원소가 DQ 안에 들어있으면 가장 앞에 들어 있을 것이다 . (DQ 에는 배열 순서대로 들어간다 .) 그 원소들을 제거하면 된다 .
실제 화분문제는 넣을 때는 하나씩 , 뺄 때는 차이가 D 미만이 될 때 까지 뺀다 . 정렬도 해야 하므로 시간복잡도는 O(NlgN) 이다 .
화분 (100 점 )
Alternative: parametric + RMQ
사과가 설명해 주겠지 (?)
광부
IOI 2007 기출이라는것 같다 .
필자가 부산을 가고 있으므로 부산에 도착할때 까지 열심히 풀어 풀이를 업로드 하도록 하겠다 .