In the i-th query, you are given two integers lili and riri. Consider the subsequence ali,ali+1,ali+2,⋯,ariali,ali+1,ali+2,⋯,ari.
We can denote the positions(the positions according to the original sequence) where an integer appears first in this subsequence as p(i)1,p(i)2,⋯,p(i)kip1(i),p2(i),⋯,pki(i) (in ascending order, i.e.,p(i)1<p(i)2<⋯<p(i)kip1(i)<p2(i)<⋯<pki(i)).
Note that kiki is the number of different integers in this subsequence. You should output p(i)⌈ki2⌉p⌈ki2⌉(i)for the i-th query.
Input
In the first line of input, there is an integer T (T≤2T≤2) denoting the number of test cases.
Each test case starts with two integers n (n≤2×105n≤2×105) and m (m≤2×105m≤2×105). There are n integers in the next line, which indicate the integers in the sequence(i.e., a1,a2,⋯,an,0≤ai≤2×105a1,a2,⋯,an,0≤ai≤2×105).
There are two integers lili and riri in the following m lines.
However, Mr. Frog thought that this problem was too young too simple so he became angry. He modified each query to l‘i,r‘i(1≤l‘i≤n,1≤r‘i≤n)li‘,ri‘(1≤li‘≤n,1≤ri‘≤n). As a result, the problem became more exciting.
We can denote the answers as ans1,ans2,⋯,ansmans1,ans2,⋯,ansm. Note that for each test case ans0=0ans0=0.
You can get the correct input li,rili,ri from what you read (we denote them as l‘i,r‘ili‘,ri‘)by the following formula:
Output
You should output one single line for each test case.
For each test case, output one line “Case #x: p1,p2,⋯,pmp1,p2,⋯,pm”, where x is the case number (starting from 1) and p1,p2,⋯,pmp1,p2,⋯,pm is the answer.
Sample Input
2 5 2 3 3 1 5 4 2 2 4 4 5 2 2 5 2 1 2 2 3 2 4
Sample Output
Case #1: 3 3 Case #2: 3 1
给出n个数,然后 m 个查询,查询对应区间的不同的数的个数 k, 以及第 (k+1)/2 个数的位置。
正序插入的主席树可以很容易的求出区间内不同数的个数,但是在求第 (k+1)/2 个数的位置时,由于树中有 L 之前的信息,不好直接查询出。
逆序插入的主席树和正序一样,都可以求出区间内不同数的个数,但在求第 (k+1)/2 个数的时候,没有 L 之前的信息,所以可以把问题转换成求这棵树上第 (k+1)/2 大的位置,就是普通的线段树了。
#include <map> #include <set> #include <list> #include <ctime> #include <cmath> #include <stack> #include <queue> #include <string> #include <vector> #include <cstdio> #include <bitset> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define lowbit(x) x & (-x) #define mes(a, b) memset(a, b, sizeof a) #define fi first #define se second #define pii pair<int, int> #define INOPEN freopen("in.txt", "r", stdin) #define OUTOPEN freopen("out.txt", "w", stdout) typedef unsigned long long int ull; typedef long long int ll; const int maxn = 2e5 + 10; const int maxm = 1e5 + 10; const ll mod = 1e9 + 7; const ll INF = 1e18 + 100; const int inf = 0x3f3f3f3f; const double pi = acos(-1.0); const double eps = 1e-8; using namespace std; int n, m; int cas, tol, T; struct Node{ int l, r; int cnt; } node[maxn * 40]; int a[maxn]; int rt[maxn]; int last[maxn]; void init() { tol = 0; mes(rt, 0); mes(last, -1); } void update(int l, int r, int &x, int y, int p, int v) { x = ++tol; node[x] = node[y]; node[x].cnt += v; if(l == r) return ; int mid = l + r >> 1; if(p <= mid) update(l, mid, node[x].l, node[y].l, p, v); else update(mid+1, r, node[x].r, node[y].r, p, v); } int query_num(int l, int r, int pl, int pr, int rt) { if(pl <= l && r <= pr) { return node[rt].cnt; } int mid = l + r >> 1; int ans = 0; if(pl <= mid) ans += query_num(l, mid, pl, pr, node[rt].l); if(pr > mid) ans += query_num(mid+1, r, pl, pr, node[rt].r); return ans; } int query_pos(int l, int r, int x, int k) { if(l == r) return l; int mid = l + r >> 1; int cnt = node[node[x].l].cnt; if(k <= cnt) return query_pos(l, mid, node[x].l, k); else return query_pos(mid+1, r, node[x].r, k-cnt); } int main() { cas = 1; scanf("%d", &T); while(T--) { init(); scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) { scanf("%d", &a[i]); } node[0].cnt = 0; for(int i=n; i>=1; i--) { if(last[a[i]] == -1) { update(1, n, rt[i], rt[i+1], i, 1); } else { int tmp; update(1, n, tmp, rt[i+1], last[a[i]], -1); update(1, n, rt[i], tmp, i, 1); } last[a[i]] = i; } printf("Case #%d:", cas++); int ans = 0; while(m--) { int l, r; scanf("%d%d", &l, &r); int tl = min((l+ans)%n+1, (r+ans)%n+1); int tr = max((l+ans)%n+1, (r+ans)%n+1); int k = query_num(1, n, tl, tr, rt[tl]); k = (k + 1) / 2; ans = query_pos(1, n, rt[tl], k); printf(" %d", ans); } printf(" "); } return 0; }