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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
struct FastScanner {
static const int BUFSIZE = 1 << 20;
int idx = 0, size = 0;
char buf[BUFSIZE];
inline char read() {
if (idx >= size) {
size = (int)fread(buf, 1, BUFSIZE, stdin);
idx = 0;
if (size == 0) return 0;
}
return buf[idx++];
}
template <typename T>
bool nextInt(T &out) {
char c = read();
if (!c) return false;
while (c <= ' ') { c = read(); if (!c) return false; }
int sign = 1;
if (c == '-') { sign = -1; c = read(); }
long long val = 0;
while (c >= '0') { val = val * 10 + (c - '0'); c = read(); }
out = (T)(val * sign);
return true;
}
};
struct PersistentSegTree {
int N;
int LOGN;
int MAXNODE;
int nodeCount;
int *leftChild;
int *rightChild;
int *sum;
vector<int> root;
PersistentSegTree(int n, int estimatedNodes)
: N(n), nodeCount(0) {
LOGN = 0;
while ((1 << LOGN) < N) ++LOGN;
MAXNODE = estimatedNodes;
leftChild = (int*)malloc(sizeof(int) * (MAXNODE));
rightChild = (int*)malloc(sizeof(int) * (MAXNODE));
sum = (int*)malloc(sizeof(int) * (MAXNODE));
if (!leftChild || !rightChild || !sum) {
fprintf(stderr, "Memory allocation failed\n");
exit(1);
}
leftChild[0] = rightChild[0] = sum[0] = 0;
root.assign(N + 1, 0);
}
inline int newNode(int from) {
int cur = ++nodeCount;
leftChild[cur] = leftChild[from];
rightChild[cur] = rightChild[from];
sum[cur] = sum[from];
return cur;
}
int update(int prev, int s, int e, int pos, int delta) {
int cur = newNode(prev);
sum[cur] = sum[prev] + delta;
if (s != e) {
int mid = (s + e) >> 1;
if (pos <= mid) {
int nl = update(leftChild[prev], s, mid, pos, delta);
leftChild[cur] = nl;
} else {
int nr = update(rightChild[prev], mid + 1, e, pos, delta);
rightChild[cur] = nr;
}
}
return cur;
}
int query(int node, int s, int e, int l, int r) const {
if (node == 0 || r < s || e < l) return 0;
if (l <= s && e <= r) return sum[node];
int mid = (s + e) >> 1;
int res = 0;
if (l <= mid) res += query(leftChild[node], s, mid, l, r);
if (r > mid) res += query(rightChild[node], mid + 1, e, l, r);
return res;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
FastScanner fs;
int N;
if (!fs.nextInt(N)) return 0;
vector<int> A(N + 1);
vector<long long> raw(N);
for (int i = 0; i < N; ++i) {
long long v;
fs.nextInt(v);
raw[i] = v;
}
vector<long long> sorted = raw;
sort(sorted.begin(), sorted.end());
sorted.erase(unique(sorted.begin(), sorted.end()), sorted.end());
int M = (int)sorted.size();
for (int i = 1; i <= N; ++i) {
A[i] = (int)(lower_bound(sorted.begin(), sorted.end(), raw[i - 1]) - sorted.begin()) + 1;
}
int LOGN = 0; while ((1 << LOGN) < N) ++LOGN;
long long estimate = 1LL * 2 * N * (LOGN + 1) + 10; // 여유분 포함
int MAXNODE = (int)estimate;
PersistentSegTree pst(N, MAXNODE);
vector<int> last(M + 1, 0);
for (int i = 1; i <= N; ++i) {
int val = A[i];
int r1 = pst.update(pst.root[i - 1], 1, N, i, +1);
if (last[val]) {
pst.root[i] = pst.update(r1, 1, N, last[val], -1);
} else {
pst.root[i] = r1;
}
last[val] = i;
}
int Q;
fs.nextInt(Q);
string out;
out.reserve((size_t)Q * 4 + Q);
int prevAns = 0;
for (int i = 1; i <= Q; ++i) {
int x, r;
fs.nextInt(x);
fs.nextInt(r);
int l = x + prevAns; // 1 ≤ l ≤ r ≤ N 보장
int ans = pst.query(pst.root[r], 1, N, l, r);
prevAns = ans;
out.append(to_string(ans));
out.push_back('\n');
}
cout << out;
return 0;
}
|