347 words
2 minutes
[BOJ] 3초 정렬
TimeLimit | MemoryLimit | Condition | TAG |
---|---|---|---|
2s | 1024MB | (3 ≤ N ≤ 200000 1 ≤ A_i ≤ 1e9) | DynamicProgramming |
음.. 일단 dp 정의까지는 어렵지 않았구요.. 상태 전이 시키고 역추적으로 들어가서 빼고나서 정렬하면 됩니다. 그래서 정렬 후에 출력하면 바로 맞을 수 잇어여 좋은 dp 문제 같습니다!
정답 코드
#include <iostream>
#include <queue>
#include <algorithm>
#include<set>
#include <map>
using namespace std;
using ll = long long;
int inf = 1e9+1000;
int nums[200'001];
int n;
int dp[200'001][4]; // dp[i][j]는 i번째 수를 보고 있을때, j번의 정렬 상태이다.
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for(int i = 0; i < n; i++){
cin >> nums[i];
}
dp[1][0] = nums[0];
dp[1][1] = 1;
dp[1][2] = 1;
dp[1][3] = 1;
for(int i = 2; i <= n; i++){
dp[i][0] = inf;
// 안돼?? 그럼 넣을게
if(dp[i-1][0] <= nums[i-1]) dp[i][0] = nums[i-1];
for(int j = 1; j < 4; j++){
// 전 위치에서 변경하고 넣는 경우?
dp[i][j] = dp[i-1][j-1];
// 전 위치에서 j를 변경하지 않고, 내가 바꿔야 되는 경우
if(dp[i-1][j] <= nums[i-1]) dp[i][j] = min(dp[i][j], nums[i-1]);
}
}
if(min({dp[n][0], dp[n][1], dp[n][2], dp[n][3]}) == inf) cout << "NO";
else {
cout << "YES\n";
vector<pair<int, int>> result;
int count = 0;
int minimum = inf;
for(int i = 0; i < 4; i++){
if(minimum > dp[n][i]){
minimum = dp[n][i];
count = i;
}
}
cout << count << "\n";
for(int i = n; i > 0; i--){
if(!count) break;
if(dp[i-1][count] > nums[i-1] || nums[i-1] > dp[i-1][count-1]){
result.push_back({i, dp[i][count--]});
}
}
sort(result.begin(), result.end());
for(auto p : result){
cout << p.first << " " << p.second << "\n";
}
}
return 0;
}