Description
Mr. Frog has an integer sequence of length n, which can be denoted as
a1,a2,⋯,an
There are m queries.
In the i-th query, you are given two integers li and ri . Consider the subsequence ali,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)ki (in ascending order, i.e., p(i)1<p(i)2<⋯<p(i)ki ).
Note that ki is the number of different integers in this subsequence. You should output p(i)⌈ki2⌉ for the i-th query.
In the i-th query, you are given two integers li and ri . Consider the subsequence ali,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)ki (in ascending order, i.e., p(i)1<p(i)2<⋯<p(i)ki ).
Note that ki is the number of different integers in this subsequence. You should output p(i)⌈ki2⌉ for the i-th query.
Input
In the first line of input, there is an integer T (
T≤2
) denoting the number of test cases.
Each test case starts with two integers n ( n≤2×105 ) and m ( m≤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×105 ).
There are two integers li and ri 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) . As a result, the problem became more exciting.
We can denote the answers as ans1,ans2,⋯,ansm . Note that for each test case ans0=0 .
You can get the correct input li,ri from what you read (we denote them as l‘i,r‘i )by the following formula:
Each test case starts with two integers n ( n≤2×105 ) and m ( m≤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×105 ).
There are two integers li and ri 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) . As a result, the problem became more exciting.
We can denote the answers as ans1,ans2,⋯,ansm . Note that for each test case ans0=0 .
You can get the correct input li,ri from what you read (we denote them as l‘i,r‘i )by the following formula:
li=min{(l‘i+ansi−1) mod n+1,(r‘i+ansi−1) mod n+1}
ri=max{(l‘i+ansi−1) mod n+1,(r‘i+ansi−1) mod n+1}
Output
You should output one single line for each test case.
For each test case, output one line “Case #x: p1,p2,⋯,pm ”, where x is the case number (starting from 1) and p1,p2,⋯,pm is the answer.
For each test case, output one line “Case #x: p1,p2,⋯,pm ”, where x is the case number (starting from 1) and p1,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
题意:给一个数列,有m个询问,每次问[l,r]区间中所有数的第一次出现的位置的中位数是多少(有点绕),强制在线。
分析:比赛时队友黄大爷临时想出了一个分块的做法卡过了这题Orz,这题的一般做法是在主席树上做二分,倒着插点建树,然后对于每个询问的l,我们都可以得到一个从l开始的权值线段树,表示每个位置上的数是否是第一次出现,然后我们对于每个询问l,r,就可以二分它的中位数的位置了直接在权值线段树中递归下去就可以了。
#include <cstdio> #include <iostream> #include <algorithm>3e #include <cstdlib> #include <cstdio> #include <set> #include <map> #include <vector> #include <stack> #include <cmath> #include <queue> #include <unordered_map> #include <cstring> #define MOD 1000000007 #define N 200005 using namespace std; typedef long long ll; int T,n,m,cnt,pos,a[N],b[N],rt[N],f[N]; struct Tree { int ls,rs,sum; }tr[N*40]; void Build(int &node,int l,int r) { node = ++cnt; tr[node].sum = 0; if(l == r) return; int mid = (l+r)>>1; Build(tr[node].ls,l,mid); Build(tr[node].rs,mid+1,r); } void Insert(int pre,int &node,int x,int l,int r) { node = ++cnt; tr[node] = tr[pre]; tr[node].sum += x; if(l == r) return; int mid = (l + r) >> 1; if(pos <= mid) Insert(tr[pre].ls,tr[node].ls,x,l,mid); else Insert(tr[pre].rs,tr[node].rs,x,mid+1,r); } int Ask(int node,int x,int l,int r) { if(l == r) return tr[node].sum; int mid = (l+r)>>1; if(x <= mid) return Ask(tr[node].ls,x,l,mid); else return tr[tr[node].ls].sum + Ask(tr[node].rs,x,mid+1,r); } int Query(int node,int k,int l,int r) { if(l == r) return l; int mid = (l+r)>>1; if(tr[tr[node].ls].sum >= k) return Query(tr[node].ls,k,l,mid); else return Query(tr[node].rs,k-tr[tr[node].ls].sum,mid+1,r); } int main() { scanf("%d",&T); for(int t = 1;t <= T;t++) { cnt = 0; memset(f,0,sizeof(f)); scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++) scanf("%d",&a[i]); printf("Case #%d:",t); Build(rt[n+1],1,n); for(int i = n;i;i--) { pos = f[a[i]]; if(pos) { Insert(rt[i+1],rt[i],-1,1,n); pos = i; Insert(rt[i],rt[i],1,1,n); } else { pos = i; Insert(rt[i+1],rt[i],1,1,n); } f[a[i]] = i; } int pre = 0; for(int i = 1;i <= m;i++) { int l,r; scanf("%d%d",&l,&r); l = (l + pre) % n + 1,r = (r + pre) % n + 1; if(l > r) swap(l,r); int k = Ask(rt[l],r,1,n); pre = Query(rt[l],(k+1)/2,1,n); printf(" %d",pre); } printf("\n"); } }