• 洛谷 P4168 [Violet]蒲公英


    我真的服了这道题了劳资调了一个下午(怒

    题目描述

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

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

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

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

    输入输出格式

    输入格式:

     

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

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

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

    令 l=(l0+x1mod 1,r=(r0+x1mod1,如果 l > r,则交换 l,r 。

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

     

    输出格式:

     

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

     

    输入输出样例

    输入样例#1: 复制
    6 3 
    1 2 3 2 1 2 
    1 5 
    3 6 
    1 5
    输出样例#1: 复制
    1 
    2 
    1
    

    说明

    对于 20% 的数据,保证 1n,m3000。

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

    这道题我调了好久!!! 就是tag那里搞反了 生气

    这道题是一道很经典的分块嘛 

    预处理出两两块之间的众数什么  而一个区间内的众数有可能是他所包括的区间的众数

    也有可能是非整块的数帮助整块内的数反败为胜 所以就需要根$n$扫一遍 然后判断这些颜色是否反败为王就可以了 细节有点多

    然后预处理是枚举起点 向后扫一遍 开一个桶存各个颜色的数量 判断与当前最大值谁更大 更新一下就可以了

    还有这颜色范围太大了要离散化

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 4 * 1e4 + 5;
    const int M = 5 * 1e4 + 2;
    int n,m,a[N],b[N],blo,k,pos[N];
    int cnt[M],s[205][205],sum[205][N],y[M];
    bool vis[N];
    
    void Init( ) {
        
        scanf("%d%d",& n,& m);
        blo = sqrt(n);
        for(int i = 1; i <= n; i++) {
            scanf("%d",& a[i]); b[i] = a[i];
        }
        sort(b + 1,b + n + 1);
        k = unique(b + 1,b + n + 1) - b - 1;
        for(int i = 1;i <= n;i ++) {
            int ss = a[i];
            a[i] = lower_bound(b + 1,b + k + 1,a[i]) - b;
            y[a[i]] = ss;
            pos[i] = (i + blo - 1) / blo;
            if(pos[i] != pos[i - 1] && i != 1) vis[i - 1] = true;
        } 
        vis[n] = true;
        for(int i = 1;i <= n;i += blo) {
            int st = (i + blo - 1) / blo;
            for(int j = 1;j <= k;j ++) cnt[j] = 0;
            int ma = 0,ma_col = 0;
            for(int j = i;j <= n;j ++) {
                cnt[a[j]] ++;
                if(cnt[a[j]] >= ma) {
                    if(cnt[a[j]] > ma) ma_col = a[j];
                    else ma_col = min(ma_col,a[j]);
                    ma = cnt[a[j]];
                }
                if(vis[j]) {
                    int ed = (j + blo - 1) / blo;
                    s[st][ed] = ma_col;
                }
            }
        }
        for(int i = 1;i <= k;i ++) cnt[i] = 0;
        for(int i = 1;i <= n;i ++) {
            cnt[a[i]] ++;
            if(vis[i]) {
                int now = (i + blo - 1) / blo;
                for(int j = 1;j <= k;j ++)
                    sum[now][j] = cnt[j];
            }
        }
    }
    
    void Solve( ) {
        
        int L,R,las = 0;
        while(m --) {
            
            int l,r;
            scanf("%d%d",& l,& r);
            L = (l + las - 1) % n + 1,R = (r + las - 1) % n + 1;
            if(L > R) swap(L,R);
            
            int lpos = (L + blo - 1) / blo;
            int rpos = (R + blo - 1) / blo;
            
            if(lpos == rpos) {
                
                for(int i = L;i <= R;i ++) cnt[a[i]] = 0;
                int ma = 0,ma_col = 0;
                for(int i = L;i <= R;i ++) {
                    cnt[a[i]] ++; 
                    if(cnt[a[i]] >= ma) {
                        if(cnt[a[i]] > ma) ma_col = a[i];
                        else ma_col = min(ma_col,a[i]);
                        ma = cnt[a[i]];
                    }
                }
                
                printf("%d
    ",y[ma_col]);
                las = y[ma_col];
            }
            else {
                int blo1 = (L + blo - 1) / blo;
                int blo2 = (R + blo - 1) / blo;
                
                int ma_col = 0,ma = 0; bool tag = false;
                if(blo1 + 1 <= blo2 - 1) {
                    ma_col = s[blo1 + 1][blo2 - 1];
                    ma = sum[blo2 - 1][ma_col] - sum[blo1][ma_col];
                    tag = true;
                }
                    
                for(int i = L;i <= blo1 * blo;i ++) cnt[a[i]] = 0;
                for(int i = R;i > (blo2 - 1) * blo;i --) cnt[a[i]] = 0;
                for(int i = L;i <= blo1 * blo;i ++) cnt[a[i]] ++;
                for(int i = R;i > (blo2 - 1) * blo;i --) cnt[a[i]] ++;
                
                for(int i = L;i <= blo1 * blo;i ++) {
                    int num = cnt[a[i]];
                    if(tag) num += (sum[blo2 - 1][a[i]] - sum[blo1][a[i]]);
                    if(num >= ma) {
                        if(num > ma) {
                            ma = num; ma_col = a[i];
                        }
                        else {
                            ma_col = min(ma_col,a[i]);
                        }
                    }
                }
                for(int i = R;i > (blo2 - 1) * blo;i --) {
                    int num = cnt[a[i]];
                    if(tag) num += (sum[blo2 - 1][a[i]] - sum[blo1][a[i]]);
                    if(num >= ma) {
                        if(num > ma) {
                            ma = num; ma_col = a[i];
                        }
                        else {
                            ma_col = min(ma_col,a[i]);
                        }
                    }
                }
                
                printf("%d
    ",y[ma_col]);
                las = y[ma_col];
            }
        }
    }
    
    int main( ) {
        
        Init( );
        Solve( );
    }
  • 相关阅读:
    数字图像、灰度直方图、色彩空间
    编译原理
    Visual studio文件中不同图标对应对象的类别
    230 前端之JQuery:JQuery属性操作
    229 前端之JQuery:JQuery基本语法
    228 前端之JavaScript:JS之DOM对象三
    227 前端之JavaScript:JS之DOM对象二
    226 前端之JavaScript:JS之DOM对象一
    225 前端之JavaScript:JavaScript对象
    021 用Vue.js搭建一个小说阅读网站
  • 原文地址:https://www.cnblogs.com/Rubenisveryhandsome/p/9663468.html
Copyright © 2020-2023  润新知