Wine Production(想法题)

原题: 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]);
}


猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/82823232
今日推荐