Problem 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 1Hint
先写了一个二分位置两个log的。。然后T了。听说现场赛可以过
然后去看了题解,发现只要倒着枚举l加入,每次只将离l最近的第一次出现的各个不同数的位置+1
这样如果询问l,r,那么就直接询问区间和就可以了
然后求k/2。因为倒着加入的,所以可以直接在线段树直接查询值为k/2的那个位置就好,这样就不需要二分那个log了
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
struct tree
{
//int l,r;
int ll,rr;
int s;
}tr[10000001];
int tot;
int rt[2000001],a[2000001];
int n;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9')
{
//if(ch=='-')f=-1;
ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void build(int l,int r)
{
int p=tot;
//tr[p].l=l;
//tr[p].r=r;
if(l!=r)
{
int mid=(l+r)/2;
tot++;
tr[p].ll=tot;
build(l,mid);
tot++;
tr[p].rr=tot;
build(mid+1,r);
tr[p].s=tr[tr[p].ll].s+tr[tr[p].rr].s;
}
else
{
tr[p].ll=0;
tr[p].rr=0;
tr[p].s=0;
}
}
inline int inc(int p,int ll,int rr,int l,int r,int x)
{
if(p==0)
return 0;
if(ll==l&&rr==r)
{
tot++;
// tr[tot].l=l;
// tr[tot].r=r;
tr[tot].s=tr[p].s+x;
return tot;
}
else
{
int mid=(ll+rr)/2;
tot++;
int pp=tot;
//tr[pp].l=tr[p].l;
// tr[pp].r=tr[p].r;
if(l<=mid)
tr[pp].ll=inc(tr[p].ll,ll,mid,l,r,x);
else
tr[pp].ll=tr[p].ll;
if(r>mid)
tr[pp].rr=inc(tr[p].rr,mid+1,rr,l,r,x);
else
tr[pp].rr=tr[p].rr;
tr[pp].s=tr[tr[pp].ll].s+tr[tr[pp].rr].s;
return pp;
}
}
inline int ask(int p2,int p1,int ll,int rr,int l,int r)
{
if(p1==0)
return 0;
if(l<=ll&&rr<=r)
return tr[p2].s-tr[p1].s;
else
{
int mid=(ll+rr)/2;
int sum=0;
if(l<=mid)
sum+=ask(tr[p2].ll,tr[p1].ll,ll,mid,l,r);
if(r>mid)
sum+=ask(tr[p2].rr,tr[p1].rr,mid+1,rr,l,r);
return sum;
}
}
inline int sx(int p,int l,int r,int x)
{
if(l==r)
return l;
int mid=(l+r)/2;
if(tr[tr[p].ll].s>=x)
return sx(tr[p].ll,l,mid,x);
return sx(tr[p].rr,mid+1,r,x-tr[tr[p].ll].s);
}
int la[2000001];
int main()
{
int T,k=0;
//scanf("%d",&T);
T=read();
while(T>0)
{
T--;
k++;
int m;
n=read();
m=read();
// scanf("%d%d",&n,&m);
int i;
for(i=1;i<=n;i++)
a[i]=read();
// scanf("%d",&a[i]);
memset(la,0,sizeof(la));
tot=1;
rt[0]=1;
build(1,n);
for(i=n;i>=1;i--)
{
if(la[a[i]]==0)
{
rt[i]=tot+1;
inc(rt[(i+1)%(n+1)],1,n,i,i,1);
la[a[i]]=i;
}
else
{
int d=tot+1;
inc(rt[(i+1)%(n+1)],1,n,la[a[i]],la[a[i]],-1);
rt[i]=tot+1;
inc(d,1,n,i,i,1);
la[a[i]]=i;
}
}
printf("Case #%d:",k);
int lx,rx,l,r;
int las=0;
for(i=1;i<=m;i++)
{
// scanf("%d%d",&lx,&rx);
lx=read();
rx=read();
l=min((lx+las)%n+1,(rx+las)%n+1);
r=max((lx+las)%n+1,(rx+las)%n+1);
//printf("\n\n%d %d\n\n",l,r);
int sum=ask(rt[l],rt[(r+1)%(n+1)],1,n,l,r);
int dx=(sum+1)/2;
int ll=sx(rt[l],1,n,dx);
printf(" %d",ll);
las=ll;
}
printf("\n");
}
return 0;
}