• P4168 [Violet]蒲公英 分块


    P4168 [Violet]蒲公英

    题目链接

    ​ 分块。

    ​ 一看到这数据范围肯定要离散化。而且强制在线,不可用莫队做。

    (p[i][j])表示第(i)个块到第(j)个块内的众数,预处理出来就好了,枚举(i)(j)(O(sqrt n))的,枚举(j)块内的数也是(O(sqrt n))的,总复杂度(O(nsqrt n))

    (sum[i][h])表示前(i)个块数字(h)出现的个数,预处理是(O(n))的。

    ​ 对于每一个查询,假设左端点(l)所在的块是(x),右端点(r)所在的块是(y),然后分情况:

    ​ 如果(y - x <= 2),直接暴力,最多扫(3 *sqrt n)个数,复杂度(O( sqrt n))

    ​ 如果(y - x > 2),我们可以确定这个众数一定出现在两边的残块中或中间的整块中,我们只需枚举残块中的每个数,用预处理出来的(sum)数组求出整个区间某个数的个数,最后在与(p[x + 1][y - 1]),比较一下就好了,最多扫(2 *sqrt n)个数,复杂度(O( sqrt n))

    #include <bits/stdc++.h>
    
    using namespace std;
    
    inline long long read() {
        long long s = 0, f = 1; char ch;
        while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
        for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
        return s * f;
    }
    
    const int N = 4e4 + 5;
    int n, m, t, len, last;
    int a[N], c[N], vis[N], pos[N], tong[N], pre[N], sum[205][N];
    struct block { int l, r; } b[N];
    struct number { int num, x; } p[205][205];
    
    void make_pre() {
        for(int i = 1;i <= t; i++) {
            number tmp; tmp.num = tmp.x = 0;
            for(int j = i;j <= t; j++) {
                for(int k = b[j].l;k <= b[j].r; k++) {
                    tong[a[k]]++;
                    if(tong[a[k]] > tmp.num) {
                        tmp.num = tong[a[k]]; tmp.x = a[k];
                    }
                    else if(tong[a[k]] == tmp.num) {
                        tmp.x = min(tmp.x, a[k]);
                    }
                }
                p[i][j] = tmp; 
            }
            for(int j = i;j <= t; j++) 
                for(int k = b[j].l;k <= b[j].r; k++) tong[a[k]] = 0;
        }
        for(int i = 1;i <= t; i++) {
            for(int j = 1;j <= n; j++) sum[i][a[j]] = sum[i - 1][a[j]];
            for(int j = b[i].l;j <= b[i].r; j++) sum[i][a[j]] ++;
        }
    }
    
    int query(int l, int r) {
        int x = pos[l], y = pos[r];
        if(y - x <= 2) {
            int tmp = 0;
            for(int i = l;i <= r; i++) tong[a[i]] = 0;
            for(int i = l;i <= r; i++) {
                tong[a[i]] ++;
                if(tong[a[i]] > tong[tmp]) tmp = a[i];
                else if(tong[a[i]] == tong[tmp]) tmp = min(tmp, a[i]);
            }
            return pre[tmp];
        }
        else {
            int ans = p[x + 1][y - 1].x, res_num = 0, res_x = 0;
            tong[ans] = vis[ans] = 0;  
            for(int i = l;i <= b[x].r; i++) tong[a[i]] = 0, vis[a[i]] = 0;
            for(int i = b[y].l;i <= r; i++) tong[a[i]] = 0, vis[a[i]] = 0;
            for(int i = l;i <= b[x].r; i++) tong[a[i]] ++;
            for(int i = b[y].l;i <= r; i++) tong[a[i]] ++;
            for(int i = l;i <= b[x].r; i++) {
                if(!vis[a[i]]) {
                    vis[a[i]] = 1;
                    int tmp = tong[a[i]] + sum[y - 1][a[i]] - sum[x][a[i]];
                    if(res_num < tmp) res_num = tmp, res_x = a[i];
                    else if(res_num == tmp) res_x = min(res_x, a[i]);
                }
            }  
            for(int i = b[y].l;i <= r; i++) {
                if(!vis[a[i]]) {
                    vis[a[i]] = 1;
                    int tmp = tong[a[i]] + sum[y - 1][a[i]] - sum[x][a[i]];
                    if(res_num < tmp) res_num = tmp, res_x = a[i];
                    else if(res_num == tmp) res_x = min(res_x, a[i]);
                }
            }
            int tmp = tong[ans] + p[x + 1][y - 1].num;
            if(res_num > tmp) ans = res_x;
            else if(res_num == tmp) ans = min(ans, res_x);
            return pre[ans];
        }
    }
    
    int main() {
        
        n = read(); m = read(); len = sqrt(n); t = (n - 1) / len + 1;
        for(int i = 1;i <= n; i++) a[i] = c[i] = read(), pos[i] = (i - 1) / len + 1, b[pos[i]].l = 2333333;
        for(int i = 1;i <= n; i++) b[pos[i]].l = min(b[pos[i]].l, i), b[pos[i]].r = max(b[pos[i]].r, i);
        sort(c + 1, c + n + 1);
        int cnt = unique(c + 1, c + n + 1) - c - 1;
        for(int i = 1;i <= n; i++) {
            int tmp = a[i];
            a[i] = lower_bound(c + 1, c + cnt + 1, a[i]) - c;
            pre[a[i]] = tmp;
        }
        make_pre(); 
        for(int i = 1, l, r;i <= m; i++) {
            l = read(); r = read();
            l = (last + l - 1) % n + 1; r = (last + r - 1) % n + 1;
            if(l > r) swap(l, r);
            printf("%d
    ", last = query(l, r));
        }
    
        return 0;
    }
    
  • 相关阅读:
    Aizu
    Aizu
    POJ
    POJ
    POJ
    UVA
    manacher
    Gym
    Gym
    Gym
  • 原文地址:https://www.cnblogs.com/czhui666/p/13727105.html
Copyright © 2020-2023  润新知