【BZOJ 2714】蒲公英

https://blog.csdn.net/nixinyis/article/details/68075234?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1

 

给一个序列,求一个区间的众数。(强制在线)

Sol:

先分块。
设f[i][j]表示第i块到第j块总的众数
然后每次对于一个询问[l,r],x到y已经知晓,
答案只可能是l~x,y~r,和块x~y的众数之一,
所以接下来要做的就是判断l~x和y~r中存不存在数字出现次数比块x到y众数出现更多的数。
不过怎么判断呢?可以先用vector来保存每个数字出现的位置
(因为本题的值域较大,所以要离散化一下,就是map来搞一搞),
在用二分答案查找这个数字在[l,r]内出现的次数即可

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#define N 40010
#define B 200
using namespace std;
map<int,int> mp;
vector<int> pos[N];
int cnt,val[N],a[N];
int belong[N],tot[N],f[B+5][B+5];
int n;
void pre(int x)
{
    int now = 0,maxnsum = 0;
    memset(tot,0,sizeof(tot));
    for(int i = (x-1)*B + 1;i <= n;i++) 
	{
        tot[a[i]] ++;
        if(tot[a[i]] > maxnsum || (tot[a[i]] == maxnsum && val[now] > val[a[i]]) )
            now = a[i],maxnsum = tot[a[i]];
        f[x][belong[i]] = now;
        //f[i][j]表示第i块到第j块总的众数
    }
}

int sigma(int l,int r,int x) 
{
    return upper_bound(pos[x].begin(),pos[x].end(),r)-lower_bound(pos[x].begin(),pos[x].end(),l);
}

int query(int l,int r)
{
    int now = f[belong[l]+1][belong[r]-1],maxnsum = sigma(l,r,now);
    for(int i = l;i <= min(r,belong[l]*B);i++)
	//左边区间 [l,min(r,belong[l]*B)
	{
        int tmp = sigma(l,r,a[i]);
        if(tmp > maxnsum || (tmp == maxnsum && val[now] > val[a[i]]) )
            now = a[i],maxnsum = tmp;
    }
    if(belong[l] != belong[r]) 
	{
        for(int i = (belong[r]-1)*B+1;i <= r;i++) 
        //左边区间 [(belong[r]-1)*B+1,r]
		{
            int tmp = sigma(l,r,a[i]);
            if(tmp > maxnsum || (tmp == maxnsum && val[now] > val[a[i]]) )
                now = a[i],maxnsum = tmp;
        }
    }
    return now;
}

int main()
{
    int m,l,r;
    int ans = cnt = 0;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++) 
	{
        scanf("%d",&a[i]);
        if(!mp[a[i]]) 
		{
            mp[a[i]] = ++cnt; 
			val[cnt] = a[i];
        }
        a[i] = mp[a[i]];
        pos[a[i]].push_back(i);
    }
    for(int i = 1;i <= n;i++) 
	    belong[i] = (i-1)/B + 1;
    for(int i = 1;i <= belong[n];i++) 
	    pre(i);

    for(int i = 1;i <= m;i++) 
	{
        scanf("%d%d",&l,&r);
        l = (l+ans-1) % n + 1; r = (r+ans-1) % n + 1;
        if(l > r) swap(l,r);
        ans = val[query(l,r)];
        printf("%d\n",ans);
    }
    return 0;
}

  

posted @ 2020-04-28 16:23  我微笑不代表我快乐  阅读(129)  评论(0编辑  收藏  举报