题目链接
题目解法
可以关注到
k
k
k 的范围很小
所以考虑与
k
k
k 有关的做法
考虑到一个性质,若
d
d
d 为严格大于
r
−
l
+
1
k
\frac{r−l+1}{k}
kr−l+1 的最小的数
那么若将
a
l
,
.
.
.
,
a
r
a_l,...,a_r
al,...,ar 从小到大排序,那么第
1
,
1
+
d
,
1
+
2
d
,
.
.
.
1,1+d,1+2d,...
1,1+d,1+2d,... 个数中必定有包含了所有合法的数
因为若未出现在其中,那么出现次数最多为
d
−
1
d-1
d−1
考虑到这些数只有
k
k
k 个左右,所以考虑找到每一个
l
−
r
l-r
l−r 中排名为
r
k
rk
rk 的数,这个可以用主席树做,然后判断即可
时间复杂度
O
(
n
k
l
o
g
n
)
O(nklog\;n)
O(nklogn)
#include <bits/stdc++.h>
using namespace std;
const int N(300100);
struct Node{
int lc,rc,tot;
}seg[N*30];
int n,q,a[N];
int idx,root[N];
vector<int> vec[N];
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
int build(int l,int r){
int p=++idx;
if(l==r) return p;
int mid=(l+r)>>1;
seg[p].lc=build(l,mid),seg[p].rc=build(mid+1,r);
return p;
}
int insert(int q,int l,int r,int pos){
int p=++idx;seg[p]=seg[q];
if(l==r){ seg[p].tot++;return p;}
int mid=(l+r)>>1;
if(mid>=pos) seg[p].lc=insert(seg[q].lc,l,mid,pos);
else seg[p].rc=insert(seg[q].rc,mid+1,r,pos);
seg[p].tot=seg[seg[p].lc].tot+seg[seg[p].rc].tot;
return p;
}
int query(int p,int q,int l,int r,int rk){
if(l==r) return l;
int ltot=seg[seg[q].lc].tot-seg[seg[p].lc].tot;
int mid=(l+r)>>1;
if(rk>ltot) return query(seg[p].rc,seg[q].rc,mid+1,r,rk-ltot);
return query(seg[p].lc,seg[q].lc,l,mid,rk);
}
int main(){
n=read(),q=read();
for(int i=1;i<=n;i++) a[i]=read();
root[0]=build(1,n);
for(int i=1;i<=n;i++) root[i]=insert(root[i-1],1,n,a[i]);
for(int i=1;i<=n;i++) vec[a[i]].push_back(i);
while(q--){
int l=read(),r=read(),k=read();
int d=ceil((r-l+1)*1.0/k);
if((r-l+1)%k==0) d++;
int ans=n+5;
for(int i=1;i<=r-l+1;i+=d){
int numb=query(root[l-1],root[r],1,n,i);
int ti=upper_bound(vec[numb].begin(),vec[numb].end(),r)-lower_bound(vec[numb].begin(),vec[numb].end(),l);
if(ti>=d) ans=min(ans,numb);
}
if(ans==n+5) puts("-1");
else printf("%d\n",ans);
}
return 0;
}