https://codeforces.com/contest/1241/problem/D
최대 300000의 쿼리에 대해서 최대 300000길이의 배열을 입력받고 문제에 나온 연산을 최소한으로 수행해서 배열을 정렬한다면, 그 연산의 횟수를 출력하는 문제다.
초기의 배열을 A(앞으로 미는 연산 수행한 그룹) + B(연산수행하지않은 그룹) + C(뒤로 미는 연산을 수행한 그룹)으로 나눈다면, A의 크기와 C의 크기의 합이 정답이 된다. (여기서 크기는 그룹에 속한 숫자의 종류개수)
A크기+C크기 = 초기배열의 크기 - B그룹의 크기 이므로, B그룹의 크기만 계산해주면 된다.
B그룹은 초기 배열에서 이미 정렬된 최대의 길이이므로, LIS와 유사하다고 볼 수 있다.
(초기배열이 1 3 1 4라면 LIS=3, 정렬된 최대길이=2 이다. LIS와 유사하지만 더 빠른 방법으로 구할 수 있다.)
먼저 배열의 각 숫자마다 제일 먼저 등장한 index를 저장할 l배열과, 제일 마지막으로 등장한 index를 저장하는 r배열을 만들어 두면 시간복잡도를 줄일 수 있다.
https://codeforces.com/blog/entry/70358
더 자세한 설명은 댓글의 dantrag님의 설명을 읽어보자
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int MAX = 300001;
const int INF = 1e9;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int q; cin >> q;
while (q--) {
int n; cin >> n;
int arr[MAX], l[MAX],r[MAX];
fill(l, l + MAX, INF);
fill(r, r + MAX,-INF);
vector<int> v;
for (int i = 0; i < n; i++) {
cin >> arr[i];
v.push_back(arr[i]);
l[arr[i]] = min(l[arr[i]], i);
r[arr[i]] = max(r[arr[i]], i);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
int res = n;
int dp[MAX] = { 0 };
dp[0] = 1;
for(int i=0; i<v.size()-1; i++){
if (r[v[i]] > l[v[i + 1]])
dp[i+1] = 1;
else
dp[i+1] = dp[i] + 1;
res = min(res, (int)v.size() - dp[i+1]);
}
cout << res << '\n';
}
}
사실 이 코드를 제출하면 time limit이 뜬다. editorial의 공식 solution 코드와 무슨 차이인지 모르겠다
#include <bits/stdc++.h>
using namespace std;
const int N = int(3e5) + 99;
const int INF = int(1e9) + 99;
int t, n;
int a[N];
int l[N], r[N];
int dp[N];
int main() {
scanf("%d", &t);
for(int tc = 0; tc < t; ++tc){
scanf("%d", &n);
for(int i = 0; i < n; ++i){
l[i] = INF;
r[i] = -INF;
dp[i] = 0;
}
vector <int> v;
for(int i = 0; i < n; ++i){
scanf("%d", a + i);
--a[i];
v.push_back(a[i]);
l[a[i]] = min(l[a[i]], i);
r[a[i]] = max(r[a[i]], i);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
int res = n;
for(int i = v.size() - 1; i >= 0; --i){
if(i + 1 == v.size() || r[v[i]] >= l[v[i + 1]]) dp[i] = 1;
else dp[i] = 1 + dp[i + 1];
res = min(res, int(v.size())- dp[i]);
}
printf("%d\n", res);
}
return 0;
}
공식 코드
'알고리즘 > 코드포스' 카테고리의 다른 글
codeforces #597 div2 D - Shichikuji and Power Grid ( MST ) (0) | 2019.11.04 |
---|---|
codeforces #597 div2 C - Constanze's Machine ( 피보나치 , 구현) (0) | 2019.11.03 |
codeforces #591 div2 C - Save the Nature (이분탐색) (0) | 2019.11.01 |
codeforces #592 div2 C - The Football season(수학, 발상) (0) | 2019.10.31 |
codeforces #596 div2 B2 - TV subscribtions hard (투포인터) (0) | 2019.10.28 |