• 蒲公英


    题目描述

    亲爱的哥哥: 
    你在那个城市里面过得好吗? 
    我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!
    它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤
    出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的…… 
    最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了
    呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!  
    哥哥你要快点回来哦! 
                                                                               爱你的妹妹 Violet 
    Azure 读完这封信之后微笑了一下。 
    “蒲公英吗……” 
    在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。 
    为了简化起见,我们把所有的蒲公英看成一个长度为 n 的序列 (a1,a2,a3,...,an),其中ai为一个正整数,表示第i棵蒲公英的种类编号。 
    而每次询问一个区间[l,r],你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。 
    注意,你的算法必须是在线的。 

    输入

    第一行两个整数n,m,表示有 n 株蒲公英, m 次询问。 
    接下来一行 n 个空格分隔的整数ai,表示蒲公英的种类 
    再接下来 m 行每行两个整数l0,r0.我们令上次询问的结果为 x(如果这是第一次询问,则x=0)。 
    令l=(l0+x-1) mod n+1,r=(r0+x-1) 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

    提示

    对于20%的数据,保证1≤n,m≤3000。
    对于100%的数据,保证1≤n≤40000,1≤m≤50000,1≤ai≤10^9

    在线求区间内的众数
    
    分块
    pre[i][j]表示在第i块(包括第i块)之前j这个数出现的次数
    f[i][j]记录第i块到第j块这段区间内的众数及其出现的次数
    (书上给的做法是用一个vector记录每个数在这个序列中出现的位置,然后在vector中lower_bound一下就可以求出出现次数,但是疯狂TLE)
    
    对每次询问a,b
    答案要么是bl[a]+1~bl[b]-1这些块的众数,要么是a~bl[a]*blo或者bl[b]-1~b之内的某个数
    
    预处理是n*sqrt(n),询问是sqrt(n)
    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e4+5;
    map<int,int>mp;
    int n,m,blo,id;
    int bl[N],v[N],cnt[N],val[N],pre[205][N];
    struct orz{
        int val,cnt;}f[205][205];
    void does()
    {
        for (int i=1;i<=bl[n];i++)
        {
            for (int j=1;j<=id;j++) pre[i][j]=pre[i-1][j];
            for (int j=(i-1)*blo+1;j<=i*blo&&j<=n;j++) pre[i][v[j]]++;
        }
    
        for (int l=1;l<=bl[n];l++)
        for (int r=l;r<=bl[n];r++)
        {
            f[l][r]=f[l][r-1];
            orz now=f[l][r];
            for (int i=(r-1)*blo+1;i<=r*blo&&i<=n;i++)
            {
                if (pre[r][v[i]]-pre[l-1][v[i]]>now.cnt || pre[r][v[i]]-pre[l-1][v[i]]==now.cnt&&val[v[i]]<val[now.val])
                {
                    now.val=v[i];
                    now.cnt=pre[r][v[i]]-pre[l-1][v[i]];
                }
            }
            f[l][r]=now;
        }
    }
    
    int ask(int a,int b)
    {
        orz ans=f[bl[a]+1][bl[b]-1];
    
        for (int i=a;i<=bl[a]*blo&&i<=b;i++)
        {
            cnt[v[i]]++;
            int t=cnt[v[i]]+max(pre[bl[b]-1][v[i]]-pre[bl[a]][v[i]],0);
            if (t>ans.cnt||t==ans.cnt&&val[v[i]]<val[ans.val]) ans.val=v[i],ans.cnt=t;
        }
    
        if (bl[a]!=bl[b])
        {
            for (int i=(bl[b]-1)*blo+1;i<=b;i++)
            {
                cnt[v[i]]++;
                int t=cnt[v[i]]+max(pre[bl[b]-1][v[i]]-pre[bl[a]][v[i]],0);
                if (t>ans.cnt||t==ans.cnt&&val[v[i]]<val[ans.val]) ans.val=v[i],ans.cnt=t;
            }
        }
    
        for (int i=a;i<=bl[a]*blo&&i<=b;i++) cnt[v[i]]--;
        if (bl[a]!=bl[b])
             for (int i=(bl[b]-1)*blo+1;i<=b;i++) cnt[v[i]]--;
    
        return ans.val;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        blo=200;
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&v[i]);
            if (!mp[v[i]])
            {
                mp[v[i]]=++id;
                val[id]=v[i];
            }
            v[i]=mp[v[i]];
        }
    
        for (int i=1;i<=n;i++) bl[i]=(i-1)/blo+1;
        does();
    
        int ans=0,a,b;
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            a=(a+ans-1)%n+1; b=(b+ans-1)%n+1;
            if (a>b) swap(a,b);
            ans=val[ask(a,b)];
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    选择排序——Java实现
    冒泡排序——Python实现
    基数排序——Java实现
    Sqoop迁移Hadoop与RDBMS间的数据
    Hive Join
    Hadoop 完全分布式部署(三节点)
    springboot自定义异常处理
    linux下安装redis
    windows 下tomcat重启脚本
    解决rabbin首次请求慢的问题
  • 原文地址:https://www.cnblogs.com/tetew/p/9748235.html
Copyright © 2020-2023  润新知