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;
    }
    
  • 相关阅读:
    Apache Shiro 的三大核心组件
    MyBatis 与 Hibernate 有哪些不同?
    #{}和${}的区别是什么?
    Java Web中前端提交的表单两种方式(处理中文乱码问题)
    Http中200、302、304、404和500等响应状态码所表示的意义?
    jsp三大指令标记,七大动作标记、详解。
    session 的工作原理
    JSP的四种作用域
    jsp有哪些内置对象?作用分别是什么?
    什么是session?什么是cookie?session和cookie有什么区别?
  • 原文地址:https://www.cnblogs.com/poi-bolg-poi/p/13500285.html
Copyright © 2011-2022 走看看