백준 문제풀이 (Platinum)
수열과 쿼리 5 PL2
- Mo’s 알고리즘을 이용하여 풀수 있는 문제
- count라는 배열을 이용하여 총 시간복잡도는 $O(N \sqrt N)$
- while 문 부분이 중요하므로 , 일반성을 잃지 말고 코드를 작성해야함
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int sz;
struct Q{
int i,s,e;
bool operator < (Q &x){
if(s/sz != x.s/sz) return s/sz < x.s/sz;
return e < x.e;
}
};
vector<Q> query;
int v[101010],ans[101010], cnt[1001000];
ll res = 0;
void add(int x){
if(cnt[x]++ == 0) res++;
}
void del(int x){
if(--cnt[x]==0) res--;
}
int main(void){
cin.tie(0)->sync_with_stdio(0);
int n; cin >> n ;
sz = sqrt(n);
for(int i = 1; i<=n;i++) cin >> v[i];
int q; cin >> q;
for(int i = 0; i<q;i++){
int s,e; cin >> s >> e;
query.push_back({i,s,e});
}
sort(query.begin(), query.end());
int s = query[0].s, e = query[0].e;
for(int i = s ; i<=e;i++) {
if(cnt[v[i]] == 0) res++;
cnt[v[i]]++;
}
ans[query[0].i] = res;
for(int i = 1; i<q;i++){
while(s < query[i].s) del(v[s++]);
while(s > query[i].s) add(v[--s]);
while(e < query[i].e) add(v[++e]);
while(e > query[i].e) del(v[e--]);
ans[query[i].i] = res;
}
for(int i = 0; i<q;i++) cout << ans[i] <<"\n";
}