백준 15325번 Doktor
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#define FOR(i, a, b) for (int (i) = (a); (i) < (b); i++)
#define REP(i, n) FOR(i, 0, n)
using namespace std;
const int MaxN = 1000100;
//everything is 1-indexed
int N;
int perm[MaxN];
vector <int> radii[2 * MaxN]; // center and radius are doubled
int prefFixedPoints[MaxN];
void findSegmentBounds(const int center, const int radius, int& left, int& right) {
left = (center - radius) / 2;
right = (center + radius) / 2;
}
int fixedPointsInSegment(int a, int b) { // [a, b]
return prefFixedPoints[b] - prefFixedPoints[a - 1];
}
void precomputePrefFixedPoints() {
//preFixedPonits[i]는 현재 고정점의 개수를 부분합으로 나타낸 배열입니다.
//3 2 4 1 의 경우에는 0 1 1 1 으로
//3 6 5 7 4 1 2 의 경우에는 0 0 0 0 0 0 0 으로 저장됩니다.
for (int i = 1; i <= N; i++)
prefFixedPoints[i] = prefFixedPoints[i - 1] + (perm[i] == i);
}
void findCenters() {
for (int i = 1; i <= N; i++)
radii[perm[i] + i].push_back(abs(perm[i] - i));
for (int center = 2; center <= N + N; center++) { // 가능한 center들
//sort로 정렬을 해주는 이유는 같은 센터의 경우 반지름이 크면 클수록 회전했을 때 얻을 수 있는 경우가 1씩 늘어나기 때문입니다.
//회전했을때 잃는 고정점의 개수는 아직 고려하지 않았습니다.
sort(radii[center].begin(), radii[center].end()); // the log in the complexity may be evaded by smart insertion
}
}
void findBestFlip() {
int targetMax = -MaxN, targetLeft = -1, targetRight = -1;
for (int center = 2; center <= N + N; center++) {
int numOfCreatedFixedPoints = 0;
for (auto radius : radii[center]) {
numOfCreatedFixedPoints++;
int left, right;
findSegmentBounds(center, radius, left, right);
int numOfLostFixedPoints = fixedPointsInSegment(left, right); //left,right 범위에서 뒤집으면 잃을 수 있는 고정점 개수
int res = numOfCreatedFixedPoints - numOfLostFixedPoints; // 생성되는 고정점개수-없어지는 고정점개수 ->변경하여 얻어지는 고정점+/- 개수
//고정점개수 이때까지 변경한 것중에서 최대로 만드는 범위 찾기
if (targetMax < res) {
targetMax = res;
targetLeft = left;
targetRight = right;
}
}
}
printf("%d %d\n", perm[targetLeft], perm[targetRight]);
}
void load() {
scanf("%d", &N);
for (int i = 1; i <= N; i++)
scanf("%d", perm + i);
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
load();
precomputePrefFixedPoints();
findCenters();
findBestFlip();
return 0;
}
출처: Contest > Croatian Open Competition in Informatics > COCI 2017/2018 > Contest #2 3번
https://www.acmicpc.net/problem/15324
이 코드는 Contest #2 대회 솔루션 코드입니다. 그대로 복사 해왔어요.
문제를 풀 때 회전축 의 경우가
1. i 와 i+1 사이인 경우
2. i 인 경우
두가지를 모두 동시에 해결해서 풀 수 있는 간결한 코드입니다.
이 코드를 참조해서 나중에 제가 코드 짜보고 첨부하겠습니다.
'알고리즘 > BAEKJOON' 카테고리의 다른 글
| 백준 11780번 플로이드2 (0) | 2019.03.26 |
|---|---|
| 백준 11404번 플로이드 (0) | 2019.03.26 |
| 백준 16719번 ZOAC (0) | 2019.03.25 |
| 백준 1158번 조세퍼스 문제 (0) | 2019.03.24 |
| 백준 1149번 RGB거리 (0) | 2019.03.23 |