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;
}
  |