题意
给出一个序列 a [ 1.. n ] a[1..n] a[1..n], m m m 次询问区间 [ L , R ] [L,R] [L,R] 可以选多少个数(相同的数最多选 K K K 个),强制在线
题解
先求出每个
i
i
i 能被选到的最右的位置
t
o
[
i
]
to[i]
to[i] 如果右边区间里面的
a
[
i
]
a[i]
a[i]
个数小于
K
K
K,说明每个
a
[
i
]
a[i]
a[i] 可以被选到,即
t
o
[
i
]
=
n
+
1
to[i]=n+1
to[i]=n+1;如果大于
K
K
K,则
t
o
[
i
]
to[i]
to[i]为它右边第
K
K
K个的位置。主席树维护一下对不同的
i
i
i的答案
#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#include<set>
#include<vector>
#include<stack>
#include <utility>
#include<list>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<time.h>
#include<random>
using namespace std;
#include<ext/pb_ds/priority_queue.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#include<ext/rope>
using namespace __gnu_cxx;
#define int long long
#define PI acos(-1.0)
#define eps 1e-9
#define lowbit(a) ((a)&-(a))
#define mid ((l+r)>>1)
const int mod = 1e9+7;
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
const int INF = 0x3f3f3f3f;
const int N = 1e5+10;
struct node{
int l,r;
int w;
}hjt[N*40];
int cnt,root[N],a[N],to[N],n,m,k,last;
vector<int>v[N];
void build(int &now,int l,int r){
hjt[now=++cnt]={0,0,0};
if(l==r)return;
build(hjt[now].l,l,mid),build(hjt[now].r,mid+1,r);
}
void insert(int &now,int pre,int l,int r,int pos){
hjt[now=++cnt]=hjt[pre];
hjt[now].w++;
if(l==r)return;
if(pos<=mid)insert(hjt[now].l,hjt[pre].l,l,mid,pos);
else insert(hjt[now].r,hjt[pre].r,mid+1,r,pos);
}
int query(int now,int l,int r,int ql,int qr){
if(!now)return 0;
if(ql<=l&&r<=qr)return hjt[now].w;
int ans=0;
if(ql<=mid)ans+=query(hjt[now].l,l,mid,ql,qr);
if(qr>mid)ans+=query(hjt[now].r,mid+1,r,ql,qr);
return ans;
}
#define endl '\n'
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=n;i>=1;i--){
int sz=v[a[i]].size();
if(sz<k)to[i]=n+1;
else to[i]=v[a[i]][sz-k];
v[a[i]].push_back(i);
}
build(root[0],1,n+1);
for(int i=1;i<=n;i++)insert(root[i],root[i-1],1,n+1,to[i]);
cin>>m;
while(m--){
int l,r; cin>>l>>r;
l=(l+last)%n+1,r=(r+last)%n+1;
if(l>r)swap(l,r);
last=query(root[r],1,n+1,r+1,n+1)-query(root[l-1],1,n+1,r+1,n+1);
cout<<last<<endl;
}
}