https://codeforces.com/contest/1374/problem/F
소팅 문제에서 inversion개수로 규칙찾기
<문제설명>
원소의 수가 n개인 배열 a에서 다음 연산을 최대 $n^2$번 수행하여 정렬하여라. 정렬 못하면 -1 출력
<풀이>
1. i번째 원소를 맨 앞으로 가져올 수 있다.
2. a의 원소가 모두 distinct하면 위 operation으로 inversion 개수의 parity를 바꿀 수 없다. 따라서 이 때 inversion 개수의 parity가 홀수면 정렬 불가능하다.
3. a의 원소에 중복 원소가 있다면 일단 distinct한 배열로 바꿔준 후에, inversion 개수의 parity가 홀수라면 중복 원소 한 쌍을 swap하여 parity를 짝수로 맞춰주면 된다.
예를들어 $a = [2,1,3,3,4]$인 경우 일단 distinct한 배열로 바꿔서 $a=[2,1,3,4,5]$로 만들어 준다.
그 후에 inversion개수 parity가 홀수였으므로 중복원소 쌍 3,3 의 순서를 바꿔준다. $a=[2,4,1,3,5]$
그리고 나서 1번 성질을 이용한 sorting을 해주면 된다.
<코드>
int n, a[MAX];
P b[MAX];
vector<int> g[MAX];
void shift_(int i) {
int temp = a[i+2];
a[i+2] = a[i+1];
a[i+1] = a[i];
a[i] = temp;
}
void solve() {
for (int i = 0; i < MAX; i++) g[i].clear();
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
g[a[i]].push_back(i);
b[i] = { a[i], i };
}
bool flag = 0;
int inversion = 0;
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
if (a[i] > a[j]) inversion++;
sort(b + 1, b + n + 1);
for (int i = 1; i <= n; i++) {
for (int j = 1,x,y; j <= n; j++) {
tie(x, y) = b[j];
if (j > 1 && b[j - 1].first == x) flag = 1;
if (a[i] == x && i == y) a[i] = j;
}
}
if (!flag && inversion%2 != 0) {
cout << -1 << '\n';
return;
}
if (flag && inversion%2 != 0) {
for (int i = 1; i < MAX; i++) if (g[i].size() > 1) {
swap(a[g[i][0]], a[g[i][1]]);
break;
}
}
vector<int> ans;
for (int i = 1; i <= n; i++) {
int pos = 0;
for (int j = i; j <= n; j++) if (a[j] == i) {
pos = j;
break;
}
if (pos % 2 == i % 2) {
while (1) {
if (pos == i) break;
pos -= 2;
ans.push_back(pos);
shift_(pos);
}
}
else {
while (1) {
if (i + 1 == pos) break;
pos -= 2;
ans.push_back(pos);
shift_(pos);
}
ans.push_back(pos-1);
ans.push_back(pos-1);
shift_(pos - 1);
shift_(pos - 1);
}
}
cout << ans.size() << '\n';
for (int i : ans) cout << i << " ";
cout << '\n';
}
int main() {
FAST;
int tt; cin >> tt;
while (tt--) solve();
}
'알고리즘 > 코드포스' 카테고리의 다른 글
cf #656 div3 E - Directing Edges(위상정렬, 사이클 유무) (0) | 2020.07.20 |
---|---|
2019-2020 ICPC, Asia Jakarta Regional - H. Twin Buildings(수학, 기하) (0) | 2020.04.20 |
cf #621 div1&2 D - Cow and Fields (그리디, 정렬, 그래프) (0) | 2020.04.17 |
cf #632 div2 C - Eugene and an array (투포인터) (0) | 2020.04.13 |
cf #538 div2 C - Trailing Loves (소인수분해, 수학) (0) | 2020.04.02 |