• 【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
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    C++多态性的总结
    php 基于curl 实现,模拟多线程任务
    php 解决跨域问题
    vue-cli 使用步骤
    php 图片转成base64 前后台示例
    jq 实现选项卡效果
    javascript仿es6的map类
    PHP生成word并可下载
    vue 实现的树形菜单
    vue之路由的基本用法
  • 原文地址:https://www.cnblogs.com/cutemush/p/12795048.html
Copyright © 2020-2023  润新知