zoukankan      html  css  js  c++  java
  • BZOJ4241: 历史研究(回滚莫队)

    题意

    给出$n$个数,每次询问区间$[L, R]$内 每个数*出现次数 的最大值

    Sol

    回滚莫队,名字真萌qwq

    考虑如果用正常莫队的话我们是无法删除的,因为一旦删除了最大元素就无法找到次大元素

    这时候有人提出了一种新的计算方式

    思想很简单:对于每个询问按照左端点的块的编号进行排序,相同的话按又端点排序

    然后暴力计算每个块。

    如果询问的两个端点在同一个块中,直接暴力计算,时间复杂度$O(sqrt{n})$

    如果不在同一个块中,这时候右端点是不断递增的,因此暴力计算右端点的复杂度为$O(n)$

    但是左端点的位置在块内可是飘忽不定的啊qwq

    简单,每次询问之后把左端点移动到所在块的最右段即可,每次计算左端点的复杂度为$O(sqrt{n})$

    因为有$sqrt{n}$个块,因此总的时间复杂度为$O(sqrt{n}n)$

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define LL long long 
    using namespace std;
    const int MAXN = 1e5 + 10, INF = 1e9 + 7;
    inline int read() {
        char c = getchar(); int x = 0, f = 1;
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int N, Q;
    LL out[MAXN], ans;
    int be[MAXN], date[MAXN], cnt[MAXN], a[MAXN], tot, base, num;
    struct Query {
        int l, r, id;
        bool operator < (const Query &rhs) const {
            return be[l] == be[rhs.l] ? r < rhs.r : be[l] < be[rhs.l];
        }
    }q[MAXN];
    LL solve(int l, int r) {
        static int tim[MAXN]; LL ans = 0;
        for(int i = l; i <= r; i++) tim[a[i]] = 0;
        for(int i = l; i <= r; i++) tim[a[i]]++, ans = max(ans, 1ll * tim[a[i]] * date[a[i]]);
        return ans;
    }
    void Add(int x) {
        cnt[a[x]]++;
        ans = max(ans, 1ll * cnt[a[x]] * date[a[x]]);
    }
    void Del(int x) {
        cnt[a[x]]--;
    }
    int Get(int i, int id) {
        int R = min(N, id * base), ql = R + 1, qr = ql - 1; ans = 0;
        memset(cnt, 0, sizeof(cnt));
        for(; be[q[i].l] == id; i++) {
            if(be[q[i].l] == be[q[i].r]) {out[q[i].id] = solve(q[i].l, q[i].r); continue;}
            while(qr < q[i].r) Add(++qr);
            LL cur = ans;
            while(ql > q[i].l) Add(--ql);
            out[q[i].id] = ans;
            while(ql < R + 1) Del(ql++);//每次询问完之后重新统计答案
            ans = cur;
        }
        return i;
    }
    main() {
        //freopen("4241.in", "r", stdin);
        //freopen("4241.out", "w", stdout);
        N = read(); Q = read(); base = sqrt(N);
        for(int i = 1; i <= N; i++) {
            a[i] = date[i] = read(); be[i] = (i - 1) / base + 1;
            num = max(num, be[i]);
        }
    
        sort(date + 1, date + N + 1);
        int tot = unique(date + 1, date + N + 1) - date - 1;
        for(int i = 1; i <= N; i++) a[i] = lower_bound(date + 1, date + N + 1, a[i]) - date;
    
        for(int i = 1; i <= Q; i++) q[i].l = read(), q[i].r = read(), q[i].id = i;
        sort(q + 1, q + Q + 1);
    
        for(int i = 1, id = 1; id <= num; id++) 
            i = Get(i, id);
        
    
        for(int i = 1; i <= Q; i++)
            printf("%lld
    ", out[i]);
        return 0;
    }
    /*
    2
    3 2
    1 2 3
    2 2
    1 3
    3 2
    1 2 3
    2 2
    1 3
    
    */
  • 相关阅读:
    Python正则表达式re模块
    time,datetime,calendar模块
    Python的特殊属性和魔法函数
    Django环境搭建
    第十二篇 os模块
    第十一篇 logging模块
    Page Object设计模式
    实现自动发邮件功能
    cs61a Mutable Data 2 学习笔记和补充
    Lambda Expressions and Higher-Order Functions 学习笔记和习题解答
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/9645158.html
Copyright © 2011-2022 走看看