SHOW:
|
|
- or go back to the newest paste.
| 1 | #include<bits/stdc++.h> | |
| 2 | using namespace std; | |
| 3 | ||
| 4 | ||
| 5 | template<typename T> | |
| 6 | class persistent_segtree | |
| 7 | {
| |
| 8 | public: | |
| 9 | ||
| 10 | int n, m; | |
| 11 | vector<int> root, lc, rc; | |
| 12 | vector<T> st; | |
| 13 | int FREE_ID = 0; | |
| 14 | ||
| 15 | persistent_segtree() {}
| |
| 16 | ||
| 17 | persistent_segtree(int n_, int m_, T val = T()) | |
| 18 | {
| |
| 19 | n = n_; | |
| 20 | m = m_; | |
| 21 | FREE_ID = 0; | |
| 22 | root.resize(n + 2); | |
| 23 | st.resize(m + 2, val); | |
| 24 | lc.resize(m + 2); | |
| 25 | rc.resize(m + 2); | |
| 26 | } | |
| 27 | ||
| 28 | T merge(T a, T b) | |
| 29 | {
| |
| 30 | T res = a + b; | |
| 31 | return res; | |
| 32 | } | |
| 33 | ||
| 34 | int build(int l, int r) // create one dummy tree | |
| 35 | {
| |
| 36 | int node = ++FREE_ID; | |
| 37 | if (l == r) | |
| 38 | {
| |
| 39 | return node; | |
| 40 | } | |
| 41 | int mid = (l + r) >> 1; | |
| 42 | lc[node] = build(l, mid); | |
| 43 | rc[node] = build(mid + 1, r); | |
| 44 | return node; | |
| 45 | } | |
| 46 | ||
| 47 | int update(int prev, int ss, int se, int pos, int val) | |
| 48 | {
| |
| 49 | int node = ++FREE_ID; | |
| 50 | if (ss == se) | |
| 51 | {
| |
| 52 | st[node] = val; | |
| 53 | return node; | |
| 54 | } | |
| 55 | lc[node] = lc[prev]; | |
| 56 | rc[node] = rc[prev]; | |
| 57 | int mid = (ss + se) >> 1; | |
| 58 | if (pos <= mid) | |
| 59 | {
| |
| 60 | lc[node] = update(lc[prev], ss, mid, pos, val); | |
| 61 | } | |
| 62 | else | |
| 63 | {
| |
| 64 | rc[node] = update(rc[prev], mid + 1, se, pos, val); | |
| 65 | } | |
| 66 | st[node] = merge(st[lc[node]], st[rc[node]]); | |
| 67 | return node; | |
| 68 | } | |
| 69 | ||
| 70 | T query(int node, int ss, int se, int qs, int qe) | |
| 71 | {
| |
| 72 | if (qs > se || qe < ss) | |
| 73 | {
| |
| 74 | return T(); | |
| 75 | } | |
| 76 | if (qs <= ss && se <= qe) | |
| 77 | {
| |
| 78 | return st[node]; | |
| 79 | } | |
| 80 | int mid = (ss + se) >> 1; | |
| 81 | T res = merge(query(lc[node], ss, mid, qs, qe), query(rc[node], mid + 1, se, qs, qe)); | |
| 82 | return res; | |
| 83 | } | |
| 84 | ||
| 85 | }; | |
| 86 | ||
| 87 | const int N = 1e5 + 5; | |
| 88 | ||
| 89 | int a[N], val[N]; | |
| 90 | vector<int> adj[N]; | |
| 91 | int n, k, q; | |
| 92 | persistent_segtree<int> obj; | |
| 93 | ||
| 94 | signed main() | |
| 95 | {
| |
| 96 | ios_base::sync_with_stdio(false); | |
| 97 | cin.tie(NULL); cout.tie(NULL); | |
| 98 | ||
| 99 | #ifndef ONLINE_JUDGE | |
| 100 | freopen("input.txt", "r", stdin);
| |
| 101 | freopen("output.txt", "w", stdout);
| |
| 102 | #endif | |
| 103 | ||
| 104 | cin >> n >> k; | |
| 105 | for (int i = 1; i <= n; i++) | |
| 106 | {
| |
| 107 | cin >> a[i]; | |
| 108 | adj[a[i]].push_back(i); | |
| 109 | int sz = adj[a[i]].size(); | |
| 110 | val[i] = 0; | |
| 111 | if (sz > k) | |
| 112 | {
| |
| 113 | val[i] = adj[a[i]][sz - k - 1]; | |
| 114 | } | |
| 115 | } | |
| 116 | ||
| 117 | cin >> q; | |
| 118 | int sz1 = n << 1; | |
| 119 | int sz2 = (log2(n) + 1) * (sz1 + 1); | |
| 120 | sz2 <<= 1; | |
| 121 | obj = persistent_segtree<int> (sz1, sz2); | |
| 122 | obj.root[0] = obj.build(1, n); | |
| 123 | ||
| 124 | for (int i = 1; i <= n; i++) | |
| 125 | {
| |
| 126 | obj.root[i] = obj.update(obj.root[i - 1], 1, n, i, +1); | |
| 127 | if (val[i]) | |
| 128 | {
| |
| 129 | obj.root[i] = obj.update(obj.root[i], 1, n, val[i], 0); | |
| 130 | } | |
| 131 | } | |
| 132 | ||
| 133 | ||
| 134 | int last = 0; | |
| 135 | for (int i = 1; i <= q; i++) | |
| 136 | {
| |
| 137 | int x, y; | |
| 138 | cin >> x >> y; | |
| 139 | int l = ((x + last) % n) + 1; | |
| 140 | int r = ((y + last) % n) + 1; | |
| 141 | if (l > r) | |
| 142 | {
| |
| 143 | swap(l, r); | |
| 144 | } | |
| 145 | last = obj.query(obj.root[r], 1, n, l, r); | |
| 146 | cout << last << endl; | |
| 147 | } | |
| 148 | ||
| 149 | return 0; | |
| 150 | } |