• bzoj2724 [Violet 6]蒲公英


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2724

    【题解】

    比较经典的区间求众数问题。

    我们考虑分块,ans[i,j]表示第i个块到第j个块答案是多少,这个可以预处理。

    然后离散值,对于每个值存一个vector,里面存的是出现这个值的所有下标。

    可以证明,答案只会在整块的答案和两端部分的所有数中选择,那么提取这些数,排序。

    可以在vector中二分出出现的位置。就能求有多少个了,然后比较即可。

    复杂度O(n根号nlogn)

    # include <vector>
    # include <stdio.h>
    # include <string.h>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 4e4 + 10, N = 310, BLOCK = 200;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, m, a[M], bl[M], B, q;
    int ans[N][N];
    int bst[N], bnd[N];
    vector<int> ps, tt, g[M];
    int t[M], mx, mxid, lst;
    
    inline void prepare(int x) {
        int tem = x;
        mx = 0; mxid = 2333333;
        for (int i=(x-1)*BLOCK+1; i<=n; ++i) {
            t[a[i]] ++;
            if(t[a[i]] > mx) {
                mx = t[a[i]];
                mxid = a[i];
            } else if(t[a[i]] == mx) {
                if(a[i] < mxid) mxid = a[i];
            }
            if(i == bnd[tem]) {
                ans[x][tem] = mxid;
                ++tem;
            }
        }
        for (int i=(x-1)*BLOCK+1; i<=n; ++i) --t[a[i]];
    }
    
    int main() {
        scanf("%d%d", &n, &q); 
        for (int i=1; i<=n; ++i) {
            scanf("%d", &a[i]);
            ps.push_back(a[i]);
        }
        sort(ps.begin(), ps.end());
        ps.erase(unique(ps.begin(), ps.end()), ps.end());
        for (int i=1; i<=n; ++i) {
            a[i] = lower_bound(ps.begin(), ps.end(), a[i]) - ps.begin() + 1;
    //        printf("%d ", a[i]);
            g[a[i]].push_back(i);
        }
    //    puts("
    ================");
        m = ps.size();
    //    for (int i=1; i<=m; ++i) {
    //        printf("==size = %d
    ", g[i].size());
    //        for (int j=0; j<g[i].size(); ++j) printf("%d ", g[i][j]);
    //        puts("");
    //    }
        for (int i=1; i<=n; ++i) bl[i] = (i-1)/BLOCK+1;
        B = bl[n]; 
        for (int i=1; i<=B; ++i) bst[i] = (i-1)*BLOCK+1, bnd[i] = min(n, i*BLOCK);
        for (int i=1; i<=B; ++i) prepare(i);
        lst = 0;
        while(q--) {
            int l, r; scanf("%d%d", &l, &r);
            l = (l+lst-1+n)%n+1;
            r = (r+lst-1+n)%n+1;
            if(l > r) swap(l, r);
            if(bl[l] == bl[r]) {
                mx = 0, mxid = 2333333;
                for (int i=l; i<=r; ++i) {
                    t[a[i]] ++;
                    if(t[a[i]] > mx) {
                        mx = t[a[i]];
                        mxid = a[i];
                    } else if(t[a[i]] == mx) {
                        if(a[i] < mxid) mxid = a[i];
                    }
                }
                for (int i=l; i<=r; ++i) --t[a[i]]; 
                printf("%d
    ", lst = ps[mxid-1]);
            } else {
                tt.clear();
                if(bl[l] + 1 != bl[r]) tt.push_back(ans[bl[l]+1][bl[r]-1]);    
                for (int i=l; i<=bnd[bl[l]]; ++i) tt.push_back(a[i]);
                for (int i=bst[bl[r]]; i<=r; ++i) tt.push_back(a[i]);
                sort(tt.begin(), tt.end());
                tt.erase(unique(tt.begin(), tt.end()), tt.end()); 
    //            for (int i=0, sz=tt.size(); i<sz; ++i) printf("%d ", tt[i]);
    //            puts("
    ======");
                mx = 0, mxid = 2333333;
                for (int i=0, sz=tt.size(); i<sz; ++i) {
                    int x = tt[i];
                    int xi = upper_bound(g[x].begin(), g[x].end(), r)-g[x].begin(), xj = lower_bound(g[x].begin(), g[x].end(), l)-g[x].begin()+1; 
    //                printf("l = %d, r = %d
    ", xj, xi);
                    int times = upper_bound(g[x].begin(), g[x].end(), r)-lower_bound(g[x].begin(), g[x].end(), l);
    //                printf("x=%d, times=%d
    ", tt[i], times);
                    if(times > mx) mx = times, mxid = x;
                }
                printf("%d
    ", lst = ps[mxid-1]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Android核心分析 ---- 电话系统之GSMCallTacker
    Android核心分析 ----- Android电话系统之RIL-Java
    Android核心分析 ------ 电话系统之rilD
    Android核心分析 ----- Android电话系统-概述篇
    AndroidRuntime 流程
    关于++和--运算符的理解
    使用eclips开发java时的闪退问题
    Android--控件的滑动事件
    Running Hero.
    软件工程第三次大作业分工说明
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj2724.html
Copyright © 2020-2023  润新知