SP32900
还是板子题。
题目要求比较一个区间的众数的 \(k\) 倍与区间长度的大小,其实还是求出现次数最多的数的出现次数。
数据范围也比较温柔,那就普通莫队跑一下就好了。
只需要维护每个数的出现次数以及每种出现次数对应的数的个数,并判断区间伸缩在什么情况下对当前答案有影响即可。
其实比较好判断:
-
当区间伸的时候,因为只加不删,答案不会更劣,所以不断取最大值即可;
-
当区间缩的时候,要判断当前删除的这个数是不是唯一的众数,如果是则答案随其一起变小。
对于数据离散化后按上面的规则跑莫队,对每组询问跑完后判断一下当前答案的 \(k\) 倍与区间长度的大小即可。
#include<cmath>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define maxn 500100
#define INF 0x3f3f3f3f
//#define int long long
using namespace std;
int n,m,len,L=2,R=1,tot,all,Ans;
int a[maxn],ans[maxn],cnt[maxn],b[maxn],num[maxn];
struct question{int l,r,k,now;}q[maxn];
int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
return s*w;
}
bool cmp(question a,question b){
return (a.l/len)^(b.l/len)?a.l<b.l:a.r<b.r;
}
void Add(int x){
num[cnt[x]]--;
num[++cnt[x]]++;
Ans=max(Ans,cnt[x]);
}
void Del(int x){
num[cnt[x]]--;
num[--cnt[x]]++;
if(!num[cnt[x]+1]&&Ans==cnt[x]+1) Ans--;
}
signed main(){
n=read();m=read();len=pow(n,2.0/3);
for(int i=1;i<=n;i++) b[i]=a[i]=read();
sort(b+1,b+n+1);all=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+all+1,a[i])-b;
for(int i=1,opt;i<=m;i++){
q[i].l=read();q[i].r=read();
q[i].k=read();q[i].now=i;
}
sort(q+1,q+m+1,cmp);
for(int i=1;i<=m;i++){
while(L<q[i].l) Del(a[L++]);
while(L>q[i].l) Add(a[--L]);
while(R<q[i].r) Add(a[++R]);
while(R>q[i].r) Del(a[R--]);
int lenth=q[i].r-q[i].l+1;
ans[q[i].now]=(Ans*q[i].k>=lenth?1:0);
}
for(int i=1;i<=m;i++) printf(ans[i]?"YES\n":"NO\n");
return 0;
}