zoukankan      html  css  js  c++  java
  • [hdu5247]rmq+预处理

    题意:有一个无序数组,求有多少个长度为k的区间满足把区间内的数排序后是连续的。

    思路:长度为k的区间排序后是 连续的数等价于maxval-minval等于k-1并且不同的数有k个(或者说没有相同的数),第一个条件可以用rmq快速得到区间最大值与最小值之差,第二个条件可以这样求,按区间的左边界分类预处理,遍历右边界,如果[L,R]内有相同的数,则[L,R+k]有相同的数,否则转化为判断a[R+1]是否在区间[L,R]内出现过,维护一个last数组,last[i]表示i上一次出现的位置,那么等价于判断last[a[R+1]]是否>=L,由于a[i]很大,所以需离散后处理。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef long long LL;
    #define all(a) (a).begin(), (a).end()
    const int maxn = 1e4 + 7;
     
    struct ST {
        struct Node {
            int a[22];
            int &operator [] (int x) {
                return a[x];
            }
        };
        const static int maxn = 1e6 + 7;
        vector<Node> dp;
        static int index[maxn];
        static void init_index() {
            index[1] = 0;
            for (int i = 2; i < maxn; i ++) {
                index[i] = index[i - 1];
                if (!(i & (i - 1))) index[i] ++;
            }
        }
        void init_min(vector<int> &a) {
            int n = a.size();
            dp.resize(n);
            for (int i = 0; i < n; i ++) dp[i][0] = a[i];
            for (int j = 1; (1 << j) <= n; j ++) {
                for (int i = 0; i + (1 << j) - 1 < n; i ++) {
                    dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
                }
            }
        }
        void init_max(vector<int> &a) {
            int n = a.size();
            dp.resize(n);
            for (int i = 0; i < n; i ++) dp[i][0] = a[i];
            for (int j = 1; (1 << j) <= n; j ++) {
                for (int i = 0; i + (1 << j) - 1 < n; i ++) {
                    dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
                }
            }
        }
        int query_min(int L, int R) {
            int p = index[R - L + 1];
            return min(dp[L][p], dp[R - (1 << p) + 1][p]);
        }
        int query_max(int L, int R) {
            int p = index[R - L + 1];
            return max(dp[L][p], dp[R - (1 << p) + 1][p]);
        }
    };
    int ST::index[maxn];
    ST st1, st2;
    vector<int> a, b;
    bool chk[maxn][1000];
    int last[maxn];
     
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt""r", stdin);
    #endif // ONLINE_JUDGE
        puts("Case #1:");
        int n, m;
        cin >> n >> m;
        a.resize(n);
        for (int i = 0; i < n; i ++) {
            scanf("%d", &a[i]);
        }
        b = a;
        ST::init_index();
        st1.init_max(a);
        st2.init_min(a);
        sort(all(a));
        a.erase(unique(all(a)), a.end());
        for (int i = 0; i < n; i ++) {
            b[i] = lower_bound(all(a), b[i]) - a.begin();
        }
        for (int i = 0; i < n; i ++) {
            chk[i][1] = true;
            memset(last, 0xff, sizeof(last));
            last[b[i]] = i;
            for (int L = 2; i + L - 1 < n && L <= 1000; L ++) {
                if (last[b[i + L - 1]] >= i) break;
                last[b[i + L - 1]] = i + L - 1;
                chk[i][L] = true;
            }
        }
        for (int i = 0; i < m; i ++) {
            int k;
            scanf("%d", &k);
            int ans = 0;
            for (int i = 0; i + k - 1 < n; i ++) {
                ans += st1.query_max(i, i + k - 1) - st2.query_min(i, i + k - 1) == k - 1 && chk[i][k];
            }
            printf("%d ", ans);
        }
        return 0;
    }
  • 相关阅读:
    Ubuntu 17.10 联网、jdk配置、初始化
    记一次与为知笔记的客服沟通
    C++ Primer zh 5th 思维导图
    《程序员健康指南(The Healthy Programmer)》笔记
    Learn_OpenGL_002_你好,长方形
    Learn_OpenGL_001_环境配置
    Visual Studio Community 2017 配置 OpenGL 环境
    oracle删除数据库
    oracle修改审计功能
    dataguard日志自动删除
  • 原文地址:https://www.cnblogs.com/jklongint/p/4548177.html
Copyright © 2011-2022 走看看