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

     
    设$modeleft(A ight)$表示集合$A$的众数
    那么有一个显然的定理为$modeleft(Acup B ight)in Acupleft{modeleft(B ight) ight}$
     
    需要离散化,时间复杂度$Oleft(nlogn ight)$
    分为$x$块
    设$f[i][j]$为第i块到第j块的众数,通过枚举$i$来求,时间复杂度为$Oleft(xn ight)$
    对于每个询问$left(l,r ight)$,把中间的整块里面的众数用$f$数组得到,然后边缘的暴力判断出现次数
    而出现次数的求法为:对每个权值开一个vector记录出现位置,在里面二分
    所以单次询问的复杂度为$Oleft(frac{nlogn}{x} ight)$
    那么总时间复杂度为$Oleft(nlogn ight)+Oleft(xn ight)+Oleft(frac{mnlogn}{x} ight) ge Oleft(nlogn+nsqrt{mlogn} ight)$
    当且仅当$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;
    }
  • 相关阅读:
    Python——五分钟带你弄懂迭代器与生成器,夯实代码能力
    LeetCode37 使用回溯算法实现解数独,详解剪枝优化
    LeetCode 33,在不满足二分的数组内使用二分的方法
    丰富图文详解B-树原理,从此面试再也不慌
    看完这篇让你高数不挂科之——泰勒公式
    数据结构——动手实战双向链表
    你听说过JMX么
    【网络安全】CSRF攻击详解
    【开发工具】本机安装的JDK8,启动IDEA2019没反应
    Java开发过程中的常用工具类库
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/7623926.html
Copyright © 2011-2022 走看看