蒲公英

蒲公英

题目背景

亲爱的哥哥:

你在那个城市里面过得好吗?

我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……

最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!

哥哥你要快点回来哦!

爱你的妹妹 Violet

Azure 读完这封信之后微笑了一下。

“蒲公英吗……”

题目描述

在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。

为了简化起见,我们把所有的蒲公英看成一个长度为n的序列 (a1,a2..an),其中 ai 为一个正整数,表示第i棵蒲公英的种类编号。

而每次询问一个区间 [l,r],你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。

注意,你的算法必须是在线的

输入输出格式

输入格式:

第一行两个整数 n,m ,表示有n株蒲公英,m 次询问。

接下来一行n个空格分隔的整数 ai ,表示蒲公英的种类

再接下来m 行每行两个整数 l0,r0,我们令上次询问的结果为 x(如果这是第一次询问, 则 x=0)。

令 l=(l0+x1)mod n+1,r=(r0+x1)mod n+1,如果 l>r,则交换 l,r 。

最终的询问区间为[l,r]。

输出格式:

输出m 行。每行一个整数,表示每次询问的结果。

输入输出样例

输入样例: 
6 3 
1 2 3 2 1 2 
1 5 
3 6 
1 5
输出样例: 
1 
2 
1

说明

对于 100% 的数据,保证 1n40000,1m50000,1ai109。

题目链接:https://www.luogu.org/problemnew/show/P4168


分块。设pre1[i][j](pair类型)为第i块到第j块中的众数及其出现的次数,pre2[i][j](int类型)为前i块中数字j出现的次数。处理询问时,若区间内包含整块,则利用预处理数组优化,剩下的小区间暴力查询。

#include<bits/stdc++.h>
#define N 50005
using namespace std;

int arr[N],arr2[N],BLOCK;
pair<int,int> pre1[int(sqrt(N)+5)][int(sqrt(N)+5)];
int pre2[int(sqrt(N)+5)][N]={0};
int lsh[N],sum_lsh=0;
int f(int x)
{
    return lower_bound(lsh,lsh+sum_lsh,x)-lsh+1;
}

void pre_work(int n)
{
    int num[N];
    pair<int,int>Max;

    for(int i=0;i<n;i+=BLOCK)
    {
        memset(num,0,sizeof(num));
        Max.first=Max.second=0;
        for(int j=i;j<n;j++)
        {
            int now=arr2[j];
            num[now]++;

            if(num[now]>Max.second||num[now]==Max.second&&now<Max.first)
            {
                Max.first=now;
                Max.second=num[now];
            }

            pre1[i/BLOCK][j/BLOCK]=Max;
        }
    }

    memset(num,0,sizeof(num));

    for(int i=0;i<n;i+=BLOCK)
    {
        for(int j=i;j<=i+BLOCK-1;j++)num[arr2[j]]++;
        for(int j=0;j<n;j++)pre2[i/BLOCK][j]=num[j];
    }
}

int ls[N]={0};

int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0;i<n;i++)scanf("%d",&arr[i]),lsh[sum_lsh++]=arr[i];

    sort(lsh,lsh+sum_lsh);
    sum_lsh=unique(lsh,lsh+sum_lsh)-lsh;

    for(int i=0;i<n;i++)arr2[i]=f(arr[i]);

    BLOCK=sqrt(n);
    pre_work(n);

    int ans=0;
    while(m--)
    {
        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);
        l--;
        r--;

        if(r/BLOCK-l/BLOCK<=1)
        {
            pair<int,int>Max;
            Max.first=Max.second=0;

            for(int i=l;i<=r;i++)
            {
                ls[arr2[i]]++;
                if(ls[arr2[i]]>Max.second||ls[arr2[i]]==Max.second&&arr2[i]<Max.first)
                {
                    Max.first=arr2[i];
                    Max.second=ls[arr2[i]];
                }
            }
            for(int i=l;i<=r;i++)
            {
                ls[arr2[i]]=0;
            }
            ans=lsh[Max.first-1];
            printf("%d\n",ans);
        }
        else
        {
            pair<int,int>Max=pre1[l/BLOCK+1][r/BLOCK-1];

            for(int i=l;i<=(l/BLOCK+1)*BLOCK-1;i++)
            {
                if(!ls[arr2[i]])
                {
                    ls[arr2[i]]=pre2[r/BLOCK-1][arr2[i]]-pre2[l/BLOCK][arr2[i]]+1;
                }
                else
                {
                    ls[arr2[i]]++;
                }

                if(ls[arr2[i]]>Max.second||ls[arr2[i]]==Max.second&&arr2[i]<Max.first)
                {
                    Max.first=arr2[i];
                    Max.second=ls[arr2[i]];
                }
            }

            for(int i=(r/BLOCK)*BLOCK;i<=r;i++)
            {
                if(!ls[arr2[i]])
                {
                    ls[arr2[i]]=pre2[r/BLOCK-1][arr2[i]]-pre2[l/BLOCK][arr2[i]]+1;
                }
                else
                {
                    ls[arr2[i]]++;
                }

                if(ls[arr2[i]]>Max.second||ls[arr2[i]]==Max.second&&arr2[i]<Max.first)
                {
                    Max.first=arr2[i];
                    Max.second=ls[arr2[i]];
                }
            }
            for(int i=l;i<=(l/BLOCK+1)*BLOCK-1;i++)ls[arr2[i]]=0;
            for(int i=(r/BLOCK)*BLOCK;i<=r;i++)ls[arr2[i]]=0;
            ans=lsh[Max.first-1];
            printf("%d\n",ans);
        }
    }
    return 0;
}
View Code

 

posted @ 2019-01-21 20:45  1371767389  阅读(165)  评论(0编辑  收藏  举报