zoukankan      html  css  js  c++  java
  • 【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;
    }
    

      

  • 相关阅读:
    解决UITableView中Cell重用机制导致内容出错的方法总结
    Hdu 1052 Tian Ji -- The Horse Racing
    Hdu 1009 FatMouse' Trade
    hdu 2037 今年暑假不AC
    hdu 1559 最大子矩阵
    hdu 1004 Let the Balloon Rise
    Hdu 1214 圆桌会议
    Hdu 1081 To The Max
    Hdu 2845 Beans
    Hdu 2955 Robberies 0/1背包
  • 原文地址:https://www.cnblogs.com/cutemush/p/12795048.html
Copyright © 2011-2022 走看看