[BZOJ2724][Violet 6]蒲公英

2724: [Violet 6]蒲公英

Time Limit: 40 Sec  Memory Limit: 512 MB Submit: 2404  Solved: 825 [Submit][Status][Discuss]

Description

 

Input

修正一下

l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1

Output

Sample Input

6 3
1 2 3 2 1 2
1 5
3 6
1 5

Sample Output

1
2
1

HINT

修正下:

n <= 40000, m <= 50000

 
设$mode\left(A\right)$表示集合$A$的众数
那么有一个显然的定理为$mode\left(A\cup B\right)\in A\cup\left\{mode\left(B\right)\right\}$
 
需要离散化,时间复杂度$O\left(nlogn\right)$
分为$x$块
设$f[i][j]$为第i块到第j块的众数,通过枚举$i$来求,时间复杂度为$O\left(xn\right)$
对于每个询问$\left(l,r\right)$,把中间的整块里面的众数用$f$数组得到,然后边缘的暴力判断出现次数
而出现次数的求法为:对每个权值开一个vector记录出现位置,在里面二分
所以单次询问的复杂度为$O\left(\frac{nlogn}{x}\right)$
那么总时间复杂度为$O\left(nlogn\right)+O\left(xn\right)+O\left(\frac{mnlogn}{x}\right) \ge O\left(nlogn+n\sqrt{mlogn}\right)$
当且仅当$x=\sqrt{mlogn}$时等号成立
#include <bits/stdc++.h>
using namespace std;
inline int readint(){
    int n = 0;
    char ch = getchar();
    while(!isdigit(ch)) ch = getchar();
    while(isdigit(ch)){
        n = (n << 1) + (n << 3) + (ch ^ 48);
        ch = getchar();
    }
    return n;
}
void output(int x){
    if(x > 9) output(x / 10);
    putchar(x % 10 + 48);
}
const int maxn = 40000 + 10, blk = 300 + 10, siz = maxn / blk + 10, INF = 1 << 30;
int n, m;
int a[maxn];
int b[maxn], num[maxn], cnt;
vector<int> vec[maxn];
int belong[maxn], le[blk], ri[blk];
int f[blk][blk], g[blk][blk];
inline int calc(int x, int l, int r){
    return upper_bound(vec[x].begin(), vec[x].end(), r) - lower_bound(vec[x].begin(), vec[x].end(), l);
}
int main(){
    n = readint();
    m = readint();
    for(int i = 1; i <= n; i++){
        a[i] = b[i] = readint();
    }
    sort(b + 1, b + n + 1);
    cnt = unique(b + 1, b + n + 1) - b;
    for(int i = 1; i < cnt; i++){
        num[i] = b[i];
    }
    for(int i = 1; i <= n; i++){
        a[i] = lower_bound(b + 1, b + cnt, a[i]) - b;
        vec[a[i]].push_back(i);
    }
    for(int i = 1; (i - 1) * siz + 1 <= n; i++){
        le[i] = (i - 1) * siz + 1;
        ri[i] = i * siz;
        if(ri[i] > n) ri[i] = n;
        for(int j = le[i]; j <= ri[i]; j++){
            belong[j] = i;
        }
    }
    for(int i = 1; i <= belong[n]; i++){
        f[i][i] = a[le[i]];
        g[i][i] = calc(f[i][i], le[i], ri[i]);
        for(int s, k = le[i] + 1; k <= ri[i]; k++){
            s = calc(a[k], le[i], ri[i]);
            if(s > g[i][i] || (s == g[i][i] && a[k] < f[i][i])){
                f[i][i] = a[k];
                g[i][i] = s;
            }
        }
        for(int j = i + 1; j <= belong[n]; j++){
            f[i][j] = f[i][j - 1];
            g[i][j] = calc(f[i][j], le[i], ri[j]);
            for(int s, k = le[j]; k <= ri[j]; k++){
                s = calc(a[k], le[i], ri[j]);
                if(s > g[i][j] || (s == g[i][j] && a[k] < f[i][j])){
                    f[i][j] = a[k];
                    g[i][j] = s;
                }
            }
        }
    }
    int l, r, bl, br, last = 0, ans, t;
    while(m--){
        l = (readint() + last - 1) % n + 1;
        r = (readint() + last - 1) % n + 1;
        if(l > r) swap(l, r);
        bl = belong[l];
        br = belong[r];
        ans = INF, t = 0;
        if(bl == br || bl + 1 == br){
            for(int s, i = l; i <= r; i++){
                s = calc(a[i], l, r);
                if(s > t || (s == t && a[i] < ans)){
                    ans = a[i];
                    t = s;
                }
            }
        }
        else{
            for(int s, i = l; i <= ri[bl]; i++){
                s = calc(a[i], l, r);
                if(s > t || (s == t && a[i] < ans)){
                    ans = a[i];
                    t = s;
                }                
            }
            for(int s, i = le[br]; i <= r; i++){
                s = calc(a[i], l, r);
                if(s > t || (s == t && a[i] < ans)){
                    ans = a[i];
                    t = s;
                }                
            }
            int s = calc(f[bl + 1][br - 1], l, r);
            if(s > t || (s == t && f[bl + 1][br - 1] < ans)){
                ans = f[bl + 1][br - 1];
                t = s;
            }
        }
        output(last = num[ans]);
        puts("");
    }
    return 0;
}

 

posted @ 2017-10-03 17:10  jzyy  阅读(101)  评论(0编辑  收藏  举报