题目
(n) 个数 (a_i) , (k) 为给定值, (q) 次询问。
每次问 ([l,r]) 内最多可以选多少个数,
满足同一个数的出现次数不超过 (k)
不带修,强制在线
分析
考虑对于每一种数开一个vector,然后在主席树中存入(now-k)的位置,
那么对于每次询问就是([0,l))范围内有多少个数,直接在主席树里查询即可
代码
#include <cstdio>
#include <cctype>
#include <vector>
#define rr register
using namespace std;
const int N=100101; vector<int>K[N];
inline signed iut(){
rr int ans=0,f=1; rr char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans*f;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
struct Chair{
int w[N<<5],ls[N<<5],rs[N<<5],cnt;
inline void build(int &rt,int l,int r){
w[rt=++cnt]=0; rr int mid=(l+r)>>1;
if (l<r) build(ls[rt],l,mid),build(rs[rt],mid+1,r);
}
inline void update(int &rt,int l,int r,int k){
rr int trt=++cnt,mid=(l+r)>>1;
ls[trt]=ls[rt],rs[trt]=rs[rt],w[trt]=w[rt]+1,rt=trt;
if (l==r) return;
k<=mid?update(ls[trt],l,mid,k):update(rs[trt],mid+1,r,k);
}
inline signed query(int L,int R,int l,int r,int k){
if (l==r) return w[R]-w[L];
rr int mid=(l+r)>>1;
if (k<=mid) return query(ls[L],ls[R],l,mid,k);
else return query(rs[L],rs[R],mid+1,r,k)+w[ls[R]]-w[ls[L]];
}
}Tre;
int rt[N],n,m,k,a[N];
signed main(){
n=iut(),k=iut(),Tre.build(rt[0],0,n);
for (rr int i=1;i<=n;++i){
rr int x=iut(),pos=0,len=K[x].size();
if (len>=k) pos=K[x][len-k];
Tre.update(rt[i]=rt[i-1],0,n,pos);
K[x].push_back(i);
}
for (rr int Q=iut(),lans=0;Q;--Q){
rr int l=(lans+iut())%n+1,r=(lans+iut())%n+1;
if (l>r) l^=r,r^=l,l^=r;
print(lans=Tre.query(rt[l-1],rt[r],0,n,l-1)),putchar(10);
}
return 0;
}