Mr. Frog has an integer sequence of length n, which can be denoted as
a1,a2,⋯,an
a1,a2,⋯,anThere are m queries.
In the i-th query, you are given two integers li li and ri ri. Consider the subsequence ali,ali+1,ali+2,⋯,ari 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 p1(i),p2(i),⋯,pki(i) (in ascending order, i.e., p(i)1<p(i)2<⋯<p(i)ki p1(i)<p2(i)<⋯<pki(i)).
Note that ki ki is the number of different integers in this subsequence. You should output p(i)⌈ki2⌉ p⌈ki2⌉(i)for the i-th query.
In the i-th query, you are given two integers li li and ri ri. Consider the subsequence ali,ali+1,ali+2,⋯,ari 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 p1(i),p2(i),⋯,pki(i) (in ascending order, i.e., p(i)1<p(i)2<⋯<p(i)ki p1(i)<p2(i)<⋯<pki(i)).
Note that ki ki is the number of different integers in this subsequence. You should output p(i)⌈ki2⌉ p⌈ki2⌉(i)for the i-th query.
Each test case starts with two integers n ( n≤2×105 n≤2×105) and m ( m≤2×105 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 a1,a2,⋯,an,0≤ai≤2×105).
There are two integers li li and ri 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) li‘,ri‘(1≤li‘≤n,1≤ri‘≤n). As a result, the problem became more exciting.
We can denote the answers as ans1,ans2,⋯,ansm ans1,ans2,⋯,ansm. Note that for each test case ans0=0 ans0=0.
You can get the correct input li,ri li,ri from what you read (we denote them as l‘i,r‘i li‘,ri‘)by the following formula:
li=min{(l‘i+ansi−1) mod n+1,(r‘i+ansi−1) mod n+1}
li=min{(li‘+ansi−1) mod n+1,(ri‘+ansi−1) mod n+1}
ri=max{(l‘i+ansi−1) mod n+1,(r‘i+ansi−1) mod n+1}
ri=max{(li‘+ansi−1) mod n+1,(ri‘+ansi−1) mod n+1}
For each test case, output one line “Case #x: p1,p2,⋯,pm p1,p2,⋯,pm”, where x is the case number (starting from 1) and p1,p2,⋯,pm p1,p2,⋯,pm is the answer.
2 5 2 3 3 1 5 4 2 2 4 4 5 2 2 5 2 1 2 2 3 2 4
Case #1: 3 3
Case #2: 3 1
给你n( n≤2∗105 )个数,每个数的大小 0<Ai≤2∗105 。再给你m(m ≤2∗105 )个询问。对于每个询问输入l,r,表示 Al...Ar 这个区间我们得到每个数第一次出现的位置下标的排列,假设这个区间有k个不同的数,我们得到的排列是 p1<p2<p3<...<pk ,叫你求第(k+1)/2这个数是多少?
首先 要想清楚的是 我们用主席树来记录位置i,而不是值a[i]
从后往前,复制旧的到新的,添加到新的位置,删掉旧的位置,记录 sum数组 代表区间的 值的个数,然后就是一个类似于线段树的操作了
题解:
1、我们利用主席树记录相同的数的前一个位置是多少,很容易得到区间有多少个不同的数,但是我们要得到第(k+1)/2这个数的话我们要二分去求解。时间复杂度为 O(n∗log2(n)) ,,在hdu会超时。
2、如果我们从后往前的话在当前位置 i 我们在主席树上i这个位置加1,在它之前出现的位置减1,然后我们在主席树询问区间的时候每个数都只出现一次了,就不用二分去找那个位置了,时间复杂度退化成 O(n∗log(n)) 。
#include<cstdio> #include<cstring> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<bitset> #include<set> #include<queue> #include<stack> #include<map> #include<cstdlib> #include<cmath> #define PI 2*asin(1.0) #define LL long long #define pb push_back #define pa pair<int,int> #define clr(a,b) memset(a,b,sizeof(a)) #define bug(x) printf("%d++++++++++++++++++++%d\n",x,x) #define key_value ch[ch[root][1]][0] const int MOD = 1000000007; const int N = 2e5 + 15; const int maxn = 100+ 14; const int letter = 130; const int INF = 1e9; const double pi=acos(-1.0); const double eps=1e-8; using namespace std; 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; } struct node { int lson,rson,sum; }T[36*N]; int n,q,pre[N],a[N],root[N]; int siz,ps[N]; void insert(int x,int &y,int l,int r,int d,int v){ y=++siz; T[y]=T[x],T[y].sum+=v; if(l==r) return; int mid=(l+r)>>1; if(d<=mid) insert(T[x].lson,T[y].lson,l,mid,d,v); else insert(T[x].rson,T[y].rson,mid+1,r,d,v); } int query(int x,int l,int r,int ll,int rr){ if(ll<=l&&r<=rr) return T[x].sum; int mid=(l+r)>>1; int ans=0; if(ll<=mid) ans+=query(T[x].lson,l,mid,ll,rr); if(rr>mid) ans+=query(T[x].rson,mid+1,r,ll,rr); return ans; } int find_k(int x,int l,int r,int k){ if(l==r) return l; int mid=(l+r)>>1; if(T[T[x].lson].sum>=k) return find_k(T[x].lson,l,mid,k); else return find_k(T[x].rson,mid+1,r,k-T[T[x].lson].sum); } int main(){ int T,cas=0; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&q); clr(pre,0),siz=0; clr(root,0); for(int i=1;i<=n;i++) scanf("%d",a+i); for(int i=n;i;i--){ insert(root[i+1],root[i],0,n,i,1); if(pre[a[i]]) insert(root[i],root[i],0,n,pre[a[i]],-1); pre[a[i]]=i; } ps[0]=0; for(int i=1;i<=q;i++){ int l,r; scanf("%d%d",&l,&r); l=(l+ps[i-1])%n+1,r=(r+ps[i-1])%n+1; if(l>r) swap(l,r); int mid=query(root[l],0,n,l,r); mid=(mid+1)/2; ps[i]=find_k(root[l],0,n,mid); } printf("Case #%d:",++cas); for(int i=1;i<=q;i++) printf(" %d",ps[i]); puts(""); } return 0; }