蒲公英

Deadly 提交于 2019-11-28 06:11:32

题意:给N个数,求一个区间内的众数。

思路:分块,分成sqrt(t*log2(n)))块,先预处理出每一个块到每个块中的众数,离散化,然后把询问区间分三段,第一段为l到l所在块的终止,第二段为每一段块,第三段为r块的开始到r,然后第二段用预处理的数组就能得出,第一三段,二分vector记录的下标求众数。

 

#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<cmath>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;
const int N=1e6+10;
int n,t,block;
int a[N],f[N],b[N];
vector<int> g[N];
int c[N],d[1000][1000];
void build()
{
    block=max(1,(int)(n/sqrt(t*log2(n))));
    for(int i=1;i<=n;i++)
    b[i]=(i-1)/block+1;
}
int Count(int l,int r,int val)
{
    int t=upper_bound(g[val].begin(),g[val].end(),r)-lower_bound(g[val].begin(),g[val].end(),l);
    return t;
 } 
void pre(int x)
{
    memset(c,0,sizeof(c));
    int mx=-1,ans=0;
    for(int i=(x-1)*block+1;i<=n;i++)
    {
        c[a[i]]++;
        if(c[a[i]]>mx||(c[a[i]]==mx&&a[i]<ans))
        {
            ans=a[i];
            mx=c[a[i]];
        }
        d[x][b[i]]=ans;//代表x到b[i]块的众数。 
    }
}
int query(int l,int r)
{
    int ans=d[b[l]+1][b[r]-1];
    int mx=Count(l,r,ans);
    int cnt=0;
    int up=min(r,b[l]*block);
    for(int i=l;i<=up;i++)
    {
        cnt=Count(l,r,a[i]);
        if(cnt>mx||(cnt==mx&&f[ans]>f[a[i]]))
        {
            mx=cnt;
            ans=a[i];
        }
    }
    if(b[l]!=b[r])
    {
        for (int i=(b[r]-1)*block+1;i<=r;i++)
        {
            cnt=Count(l,r,a[i]);
            if(cnt>mx||(cnt==mx&&ans>a[i]))
            {
                mx=cnt;
                ans=a[i];
            }
        }
    }
    return ans;
}
signed main()
{
    scanf("%d%d",&n,&t);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        f[i]=a[i];
    }
    build();
    sort(f+1,f+n+1);
    int m=unique(f+1,f+n+1)-f-1;
    for(int i=1;i<=n;i++)
    {
        a[i]=lower_bound(f+1,f+m+1,a[i])-f;
        g[a[i]].push_back(i);
    }
    for(int i=1;i<=b[n];i++)
    {
        pre(i);
    }
    int ans=0;
    while(t--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        l=(l+ans-1)%n+1;
        r=(r+ans-1)%n+1;
        if(l>r)
        swap(l,r);
        ans=f[query(l,r)];
        printf("%d\n",ans);
    }
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!