1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
struct Query {
int l, r, idx;
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, K;
if (!(cin >> N >> K)) return 0;
vector<int> A(N + 1);
for (int i = 1; i <= N; ++i) cin >> A[i];
int M;
cin >> M;
vector<Query> qs(M);
for (int i = 0; i < M; ++i) {
cin >> qs[i].l >> qs[i].r;
qs[i].idx = i;
}
int blockSize = max(1, (int)sqrt(N));
sort(qs.begin(), qs.end(), [&](const Query& a, const Query& b) {
int ab = a.l / blockSize, bb = b.l / blockSize;
if (ab != bb) return ab < bb;
if (ab & 1) return a.r > b.r; // 지그재그로 R 이동 최소화
return a.r < b.r;
});
// 값별 현재 구간 내 등장 위치들
vector<deque<int>> occ(K + 1);
// 거리 빈도와 √-분할 블록 카운팅
int distBlock = max(1, (int)sqrt(N) + 1);
vector<int> cntDist(N + 1, 0);
vector<int> cntBlock((N / distBlock) + 3, 0);
auto incDist = [&](int d) {
if (d <= 0) return;
++cntDist[d];
++cntBlock[d / distBlock];
};
auto decDist = [&](int d) {
if (d <= 0) return;
--cntDist[d];
--cntBlock[d / distBlock];
};
auto distOf = [&](int v) -> int {
const auto& dq = occ[v];
if ((int)dq.size() >= 2) return dq.back() - dq.front();
return 0;
};
auto addLeft = [&](int idx) {
int v = A[idx];
int oldD = distOf(v);
if (oldD) decDist(oldD);
occ[v].push_front(idx);
int newD = distOf(v);
if (newD) incDist(newD);
};
auto addRight = [&](int idx) {
int v = A[idx];
int oldD = distOf(v);
if (oldD) decDist(oldD);
occ[v].push_back(idx);
int newD = distOf(v);
if (newD) incDist(newD);
};
auto removeLeft = [&](int idx) {
int v = A[idx];
int oldD = distOf(v);
if (oldD) decDist(oldD);
if (!occ[v].empty() && occ[v].front() == idx) occ[v].pop_front();
int newD = distOf(v);
if (newD) incDist(newD);
};
auto removeRight = [&](int idx) {
int v = A[idx];
int oldD = distOf(v);
if (oldD) decDist(oldD);
if (!occ[v].empty() && occ[v].back() == idx) occ[v].pop_back();
int newD = distOf(v);
if (newD) incDist(newD);
};
auto getAnswer = [&]() -> int {
for (int b = (int)cntBlock.size() - 1; b >= 0; --b) {
if (cntBlock[b] > 0) {
int hi = min(N, (b + 1) * distBlock - 1);
for (int d = hi; d >= b * distBlock; --d) {
if (cntDist[d] > 0) return d;
}
}
}
return 0;
};
vector<int> ans(M, 0);
int curL = 1, curR = 0;
for (const auto& q : qs) {
while (curL > q.l) addLeft(--curL);
while (curR < q.r) addRight(++curR);
while (curL < q.l) removeLeft(curL++);
while (curR > q.r) removeRight(curR--);
ans[q.idx] = getAnswer();
}
for (int i = 0; i < M; ++i) {
cout << ans[i] << '\n';
}
return 0;
}
|