原题: https://cn.vjudge.net/problem/Gym-101879H
题意: n个数,每次询问l~r中的最大值K,使区间中存在至少K个数出现至少K次
解析: 莫队维护数a出现vis[a]次,出现i次的数用sum[i]个,对于每个区间,出现次数从最大开始遍历,累加出现个数到now,直到now>=现在的出现次数
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<set>
using namespace std;
#define ll long long
const ll mod=1e9+7;
const int maxn=30005;
int a[maxn],b[maxn],vis[maxn],sum[maxn];
set<int,greater<int> >num;
int blogs,pos[maxn];
struct node
{
int l,r,id;
}q[maxn];
bool cmp(node a,node b)
{
return pos[a.l]<pos[b.l]||pos[a.l]==pos[b.l]&&a.r<b.r;
}
void add(int x)
{
int o=vis[a[x]],b=o+1;
vis[a[x]]++;
sum[o]--;
if(sum[o]==0)num.erase(o);
sum[b]++;
if(sum[b]==1)num.insert(b);
}
void del(int x)
{
int o=vis[a[x]],b=o-1;
vis[a[x]]--;
sum[o]--;
if(sum[o]==0)num.erase(o);
sum[b]++;
if(sum[b]==1)num.insert(b);
}
int ans[30009];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+1+n);
int all=unique(b+1,b+1+n)-b-1;
for(int i=1;i<=n;i++)
a[i]=lower_bound(b+1,b+1+all,a[i])-b;
blogs=(int)sqrt((double)n+0.1);
for(int i=1;i<=n;i++)
pos[i]=(i-1)/blogs+1;
for(int i=1;i<=m;i++)
scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
sort(q+1,q+1+m,cmp);
int l=q[1].l,r=q[1].l-1;
for(int i=1;i<=m;i++)
{
while(r<q[i].r)
{
r++;
add(r);
}
while(l>q[i].l)
{
l--;
add(l);
}
while(l<q[i].l)
{
del(l);
l++;
}
while(r>q[i].r)
{
del(r);
r--;
}
int now=0;
int y=0;
for(set<int>::iterator it=num.begin();it!=num.end();it++ ){
int cii=*it;
if(now>=cii){y=1;ans[q[i].id]=now;break;}
now+=sum[cii];
if(now>=cii){y=1;
ans[q[i].id]=cii;break;
}
}
if(!y)ans[q[i].id]=now;
}
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
}