zoukankan      html  css  js  c++  java
  • 「题解」P5906 【模板】回滚莫队&不删除莫队

    题目

    P5906 【模板】回滚莫队&不删除莫队

    思路

    回滚莫队。
    考虑普通的莫队,添加一个数可以 (O(1)) 更新答案,只需要记录第一次出现的位置就可以。删除一个数想不到什么好的维护方式。就考虑回滚莫队。
    记录第一次出现的位置,正常拓展右区间,拓展左区间的时候注意对于左区间来说第一次出现的位置是右区间的最后一次出现的位置。

    Code

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #define MAXN 200001
    
    int max(int a, int b) { return a > b ? a : b; }
    int min(int a, int b) { return a < b ? a : b; }
    
    int n, m, a[MAXN], b[MAXN], first_[MAXN], ans[MAXN];
    int sqrn, num[MAXN], first[MAXN], last[MAXN];
    struct lsh {
        int w, id;
        friend bool operator < (lsh l1, lsh l2) {
            return l1.w < l2.w;
        }
    }l[MAXN];
    struct query {
        int x, y, id;
        friend bool operator < (query q1, query q2) {
            if (num[q1.x] != num[q2.x]) return num[q1.x] < num[q2.x];
            return q1.y < q2.y;
        }
    }q[MAXN];
    
    int main() {
        scanf("%d", &n), sqrn = sqrt(n);
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            num[i] = (i - 1) / sqrn + 1;
            l[i].w = a[i], l[i].id = i;
        }
        std::sort(l + 1, l + n + 1);
        for (int i = 1, now = 0; i <= n; ++i) {
            if (l[i].w != l[i - 1].w) ++now;
        	b[l[i].id] = now;
        }
        scanf("%d", &m);
        for (int i = 1; i <= m; ++i) {
            scanf("%d %d", &q[i].x, &q[i].y);
        	q[i].id = i;
        }
        std::sort(q + 1, q + m + 1);
        int l = 0, r = 0, lastblock = 0, maxx = 0;
        for (int i = 1; i <= m; ++i) {
        	if (num[q[i].x] == num[q[i].y]) {
                int temp = 0;
                for (int j = q[i].x; j <= q[i].y; ++j) {
                    if (first_[b[j]] == 0) first_[b[j]] = j;
                    else temp = max(temp, j - first_[b[j]]);
                }
                for (int j = q[i].x; j <= q[i].y; ++j) first_[b[j]] = 0;
                ans[q[i].id] = temp; continue;
            }
            if (num[q[i].x] != lastblock) {
                memset(first, 0, sizeof first);
                memset(last, 0, sizeof last);
                int stop = min(n, num[q[i].x] * sqrn);
                l = stop + 1, r = stop, maxx = 0;
                lastblock = num[q[i].x];
            }
            while(r < q[i].y) {
                ++r;
                if (first[b[r]] == 0) first[b[r]] = last[b[r]] = r;
                else {
                    maxx = max(maxx, r - first[b[r]]);
                    last[b[r]] = r;
                }
            }
            int l_ = l, temp = maxx;
            while(l_ > q[i].x) {
                --l_;
                if (first[b[l_]] == 0 && last[b[l_]] == 0) last[b[l_]] = l_;
                else temp = max(temp, last[b[l_]] - l_);
            }
            while(l_ < l) {
                if (last[b[l_]] < first[b[l_]]) last[b[l_]] = first[b[l_]];
                ++l_;
            }
            ans[q[i].id] = temp;
        }
        for (int i = 1; i <= m; ++i) printf("%d
    ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    理解Java中字符流与字节流的区别
    程序员常见面试问题(不定期更新)
    软链接 硬链接
    《大数据时代》读后的思考
    mysql——int(size) 中的size表示什么意思
    Access denied for user ''@'localhost' to
    Effective c++——条款03:尽可能使用const
    http——wireshark抓包分析
    vim——vim配置步骤
    正则表达式和通配符
  • 原文地址:https://www.cnblogs.com/poi-bolg-poi/p/13500285.html
Copyright © 2011-2022 走看看