zoukankan      html  css  js  c++  java
  • [模板]离散化

    离散化基于这样一种思想:当想要存储的数据的量较小,而数值较大,并且操作对象是数值时,使用数值的排名来代表数值进行操作.

    与哈希算法很相似,不过这种算法一定不会发生冲突,但是预处理复杂度为O(NlogN),单次查询的复杂度是O(logN).

     给出的数在32位有符号整数范围内.

    如果每当一个数字第一次出现时,将其记录为已出现,当下一次出现时就可以忽略它了.

    为了进行这样的记录,使用排名代表数字,使得每个数字(重复视为同一个数字)与其排名形成一一对应关系.使用discrete函数构建这种关系:

    // 假设给定的ind个数据已经复制到了dis数组中
    void discrete() {    // O(NlogN)
        sort(dis + 1, dis + 1 + ind);
        ind = unique(dis + 1, dis + 1 + ind) - dis - 1;    // unique的复杂度是O(N)
    }

    现在dis数组中就有了排序并去重后的数字,排名为i的数字为dis[i]的值.之后处理dis[i]时用i代替之.

    例如,读取到一个数字123456789,使用query函数获取其排名:

    // O(logN)
    int query(int x) { return lower_bound(dis + 1, dis + 1 + ind, x) - dis; }

    假设query(123456789)返回了5,那么检查排名为5的数字是否已经出现过了(used[5] == true),如果没有出现过就输出dis[5]并标记为已出现,否则直接读取下一个数字.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    #define SIZE 50000
    
    int s[SIZE + 10], dis[SIZE + 10], idx;
    bool used[SIZE + 10];
    
    inline int read() {
        char ch = getchar();
        int x = 0, f = 1;
        while (ch > '9' || ch < '0') {
            if (ch == '-') f = -1;
            ch = getchar();
        }
        while (ch >= '0' && ch <= '9') {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return x * f;
    }
    void discrete() {
        sort(dis + 1, dis + 1 + idx);
        idx = unique(dis + 1, dis + 1 + idx) - dis - 1;
    }
    int query(int x) { return lower_bound(dis + 1, dis + 1 + idx, x) - dis; }
    
    void solve() {
        int n = read();
        idx = 0;
        memset(used, 0, sizeof(bool) * (n + 1));
        for (int i = 1; i <= n; i++) {
            s[i] = read();
            dis[++idx] = s[i];
        }
        discrete();
    
        for (int i = 1; i <= n; i++) {
            int ns = query(s[i]);
            if (!used[ns]) {
                printf("%d ", s[i]);
                used[ns] = true;
            }
        }
        puts("");
    }
    
    int main() {
        int t;
        t = read();
        while (t--) solve();
    
        return 0;
    }
    P4305
  • 相关阅读:
    数数小木块
    Triangular Sums
    Financial Management
    阶乘因式分解(一)
    另一种阶乘问题
    韩信点兵
    Fibonacci数
    A+B Problem
    16进制的简单运算
    浅谈数据库之事务
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14255620.html
Copyright © 2011-2022 走看看