洛谷 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\n",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\n",y[ma_col]);
            las = y[ma_col];
        }
    }
}

int main( ) {
    
    Init( );
    Solve( );
}
posted @ 2018-09-17 17:41  阿澈说他也想好好学习  阅读(158)  评论(0编辑  收藏  举报