zoukankan      html  css  js  c++  java
  • BZOJ 2427 & 分块裸题

    题意:

      求区间内的众数,强制在线.

    SOL:

      推荐一个大神犇的blog,讲的还是很好的(主要我喜欢他的代码风格(逃:http://www.cnblogs.com/JoeFan/p/4248767.html

      太裸没什么意思...虽然好些但码码也挺长的...

      还是贴那个大神的代码天天看着代码打的会不会好看点>_<

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
     
    using namespace std;
     
    inline void Read(int &Num) {
        char c; c = getchar();
        while (c < '0' || c > '9') c = getchar();
        Num = c - '0'; c = getchar();
        while (c >= '0' && c <= '9') {
            Num = Num * 10 + c - '0';
            c = getchar();
        }
    }
     
    const int MaxN = 40000 + 5, MaxBlk = 200 + 5;
     
    int n, m, BlkSize, TotBlk;
    int A[MaxN], TL[MaxN], T[MaxN], Cnt[MaxN], L[MaxBlk], R[MaxBlk], First[MaxN], Last[MaxN];
    int f[MaxBlk][MaxBlk], g[MaxBlk][MaxBlk];
     
    struct ES
    {
        int Pos, Num, v;
    } E[MaxN];
     
    inline bool Cmp_Num(ES e1, ES e2) {
        if (e1.Num == e2.Num) return e1.Pos < e2.Pos;
        return e1.Num < e2.Num;
    }
    inline bool Cmp_Pos(ES e1, ES e2) {return e1.Pos < e2.Pos;}
     
    int GetNum(int Num, int x, int y) {
        if (x > y || x > E[Last[Num]].Pos || y < E[First[Num]].Pos) return 0;
        int l, r, mid, p1, p2;
        l = First[Num]; r = Last[Num];
        while (l <= r) {
            mid = (l + r) >> 1;
            if (E[mid].Pos >= x) {
                p1 = mid;
                r = mid - 1;
            }
            else l = mid + 1;
        }
        l = First[Num]; r = Last[Num];
        while (l <= r) {
            mid = (l + r) >> 1;
            if (E[mid].Pos <= y) {
                p2 = mid;
                l = mid + 1;
            }
            else r = mid - 1;
        }
        return p2 - p1 + 1;
    }
     
    int main()
    {
        Read(n); Read(m);
        for (int i = 1; i <= n; ++i) {
            Read(E[i].Num);
            E[i].Pos = i;
        }
        sort(E + 1, E + n + 1, Cmp_Num);
        int v_Index = 0;
        for (int i = 1; i <= n; ++i) {//离散化
            if (i == 1 || E[i].Num > E[i - 1].Num) ++v_Index;
            E[i].v = v_Index;
            TL[v_Index] = E[i].Num;//再映射回来
        }
        sort(E + 1, E + n + 1, Cmp_Pos);
        for (int i = 1; i <= n; ++i) A[i] = E[i].v;
        sort(E + 1, E + n + 1, Cmp_Num);
        //三次排序感觉真是浪费啊...
        for (int i = 1; i <= n; ++i) {
            if (First[E[i].v] == 0) First[E[i].v] = i;
            Last[E[i].v] = i;
        }//数字段的头尾
        BlkSize = (int)sqrt((double)n);
        TotBlk = (n - 1) / BlkSize + 1;//很不错的技巧啊
        for (int i = 1; i <= TotBlk; ++i) {//块两头
            L[i] = (i - 1) * BlkSize + 1;
            R[i] = i * BlkSize;
        }
        R[TotBlk] = n;
        for (int i = 1; i <= TotBlk; ++i) {
            for (int j = 1; j <= n; ++j) Cnt[j] = 0;
            f[i][i - 1] = 0; g[i][i - 1] = 0;
            for (int j = i; j <= TotBlk; ++j) {
                f[i][j] = f[i][j - 1];
                g[i][j] = g[i][j - 1]; 
                for (int k = L[j]; k <= R[j]; ++k) {
                    ++Cnt[A[k]];
                    if (Cnt[A[k]] > f[i][j] || (Cnt[A[k]] == f[i][j] && A[k] < g[i][j])) {
                        f[i][j] = Cnt[A[k]]; g[i][j] = A[k];//次数和数
                    }
                }
            }
        }
        memset(Cnt, 0, sizeof(Cnt));
        for (int i = 1; i <= n; ++i) T[i] = -1;
        int l, r, x, y, Ct, Ans, Cu;
        Ans = 0;
        for (int i = 1; i <= m; ++i) {
            Read(l); Read(r);
            l = (l + Ans - 1) % n + 1; r = (r + Ans - 1) % n + 1;//强制在线
            if (l > r) swap(l, r);
            x = (l - 1) / BlkSize + 1; if (l != L[x]) ++x;
            y = (r - 1) / BlkSize + 1; if (r != R[y]) --y;
            if (x > y) {    
                Ct = 0; Ans = 0;
                for (int j = l; j <= r; ++j) {
                    ++Cnt[A[j]];
                    if (Cnt[A[j]] > Ct || (Cnt[A[j]] == Ct && A[j] < Ans)) {
                        Ct = Cnt[A[j]]; Ans = A[j];
                    }
                }
                for (int j = l; j <= r; ++j) --Cnt[A[j]];
            }
            else {
                Ct = f[x][y]; Ans = g[x][y];
                for (int j = l; j < L[x]; ++j) {
                    ++Cnt[A[j]];
                    if (T[A[j]] == -1) T[A[j]] = GetNum(A[j], L[x], R[y]);
                    Cu = Cnt[A[j]] + T[A[j]];
                    if (Cu > Ct || (Cu == Ct && A[j] < Ans)) {
                        Ct = Cu; Ans = A[j];
                    }
                }
                for (int j = r; j > R[y]; --j) {
                    ++Cnt[A[j]];
                    if (T[A[j]] == -1) T[A[j]] = GetNum(A[j], L[x], R[y]);
                    Cu = Cnt[A[j]] + T[A[j]];
                    if (Cu > Ct || (Cu == Ct && A[j] < Ans)) {
                        Ct = Cu; Ans = A[j];
                    }
                }
                for (int j = l; j < L[x]; ++j) {--Cnt[A[j]]; T[A[j]] = -1;}
                for (int j = r; j > R[y]; --j) {--Cnt[A[j]]; T[A[j]] = -1;}
            }
            Ans = TL[Ans];
            printf("%d
    ", Ans);
        }
        return 0;
    }
    
    Sometimes it s the very people who no one imagines anything of. who do the things that no one can imagine.
  • 相关阅读:
    ADB 多设备中指定设备的启动
    vuex 绑定表单,多个输入框的解决办法
    vue 自动触发点击事件
    js 打印dom的所有属性
    邮件分享
    table表格 td设置固定宽度
    Echarts--Y坐标标题显示不全
    ExtJS5.0 菜鸟的第一天
    字体设置
    短信验证码+倒计时
  • 原文地址:https://www.cnblogs.com/YCuangWhen/p/5228678.html
Copyright © 2011-2022 走看看