zoukankan      html  css  js  c++  java
  • 排序、去重与离散化

    排序、去重与离散化

    1. 排序

    1.1 快速排序

    1. 快速排序

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1000010;
    
    int q[N];
    
    void quick_sort(int q[], int l, int r)
    {
        if (l >= r) return;  // 使得l恒小于等于r
        int i = l - 1, j = r + 1, x = q[l + r >> 1];  // 定义双指针和分界点
        while(i < j)
        {
            do i++; while (q[i] < x);  // x左边的数字比x小
            do j--; while (q[j] > x);  // x右边的数字比x大
            if (i < j) swap(q[i], q[j]);
        }
        quick_sort(q, l, j);  // 对x左边和右边的区间再进行快排,分界点是j
        quick_sort(q, j + 1, r);
    }
    
    int main()
    {
        int n;
        scanf("%d", &n);
    
        for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
    
        quick_sort(q, 0, n - 1);
    
        for (int i = 0; i < n; i ++ ) printf("%d ", q[i]);
    
        return 0;
    }
    

    2. 快排求第k小

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int const N = 1e5 +10;
    int k, n;
    int q[N];
    
    int quick_sort(int l, int r)
    {
        if (l >= r) return q[l];
        int i = l - 1, j = r + 1, x = q[l];
        while (i < j)
        {
            do i++; while (q[i] < x);
            do j--; while (q[j] > x);
            if (i < j) swap(q[i], q[j]);
        }
        if (j >= k - 1) quick_sort(l, j);  // 如果j指向的位置大于等于k-1,那么只需要对左半区间进行快排,右半区间无需操作,省去一半的时间
        else quick_sort(j + 1, r);
    }
    
    int main()
    {
        cin >> n >> k;
        for (int i = 0; i < n ;++i) scanf("%d", &q[i]);
        int t = quick_sort(0, n - 1);
        cout << t;
        return 0;
    }
    

    1.2 归并排序

    1. 归并排序

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 1e6 + 10;
    int tmp[N], q[N];
    
    void merge_sort(int l, int r)
    {
        if (l >= r) return ;
        int mid = (l + r) >> 1;
        int i = l, j = mid + 1, k = 0;
        merge_sort(l, mid), merge_sort(mid + 1, r);
        while (i <= mid && j <= r)
        {
            if (q[i] < q[j]) tmp[k ++] = q[i ++];
            else tmp[k ++] = q[j++];
        }
        while (i <= mid ) tmp[k ++] = q[i ++];
        while (j <= r) tmp[k ++] = q[j ++];
        for (int i = l, k = 0; i <= r; ++i) q[i] = tmp[k ++];
    }
    
    int main()
    {
        int n;
        cin >>  n;
        for (int i = 0 ; i < n ;  ++i)
            scanf("%d", &q[i]);
        merge_sort(0, n - 1);
        for (int i = 0; i < n; ++i) cout << q[i] << " ";
        return 0;
    }
    

    2. 归并排序求逆序对

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int const N = 1e7 + 10;
    int q[N], tmp[N];
    int n;
    double ans = 0;  // 记录答案
    
    void merge_sort(int l, int r)
    {
        if (l >= r) return;
        int mid = (l + r) >> 1;
        merge_sort(l, mid ), merge_sort(mid + 1, r);
        int i = l, j = mid + 1, k = 0;
        while (i <= mid && j <= r)
        {
            if (q[i] <= q[j]) tmp[k ++]  = q[i++];
            else
            {
                ans += mid - i + 1;  // 从i~mid这段的数字均为逆序对
                tmp[k++] = q[j ++];
            }
        }
        while (i <= mid ) tmp[k ++] = q[i ++];
        while (j <= r) tmp[k++] = q[j ++];
        for (int i = l, k = 0; i <= r; ++i) q[i] = tmp[k ++ ];
    }
    
    int main()
    {
        cin >> n;
        for (int i = 0 ; i < n; ++i) scanf("%d", &q[i]);
        merge_sort(0, n - 1);
        printf("%.0f", ans);
        return 0;
    }
    

    1.3 自定义排序写法

    1. 直接在结构体内重载

    #include <bits/stdc++.h>
    
    using namespace std;
    
    struct Range  // 按l从小到大排序(return l < R.l;);按l从大到小排序(return l > R.l;) 这句始终不变:(bool operator< (const Range &R)const)
    {
        int l, r;
        bool operator< (const Range &R)const
        {
            return l < R.l;  
        }
    }range[100];
    
    int main()
    {
        int n;
        cin >> n;
        for (int i = 0; i < n; ++i)
        {
            int l, r;
            cin >> l >> r;
        }
        sort(range, range + n, cmp);
        return 0;
    }
    

    2. 定义cmp函数

    #include <bits/stdc++.h>
    
    using namespace std;
    
    struct Range  
    {
        int l, r;
    }range[100];
    
    bool cmp(struct Range x, struct Range y)
    {
        return x.l < y.l;  // 按l从小到大排序(x.l < y.l),按l从大到小排序(x.l > y.l)
    }
    
    int main()
    {
        int n;
        cin >> n;
        for (int i = 0; i < n; ++i)
        {
            int l, r;
            cin >> l >> r;
        }
        sort(range, range + n, cmp);
        return 0;
    }
    

    2. 去重

        sort(a, a + cnt);
        cnt = unique(a, a + cnt) - a;  // cnt为去重后的序列长度
    

    3. 离散化

    思想
        把一个大的区间S映射到一个小的区间s,映射的原理是:大区间有很多的值没有使用,可以选择把这些值给忽略

    板子
    1. 离线离散化

    void read_discrete()
    {
        cin >> n >> m;
        for (int i = 1; i <= m; ++i)
        {
            char str[5];
            scanf("%d%d%s", &query[i].l, &query[i].r, str);
            query[i].ans = (str[0] == 'o'? 1: 0);
            a[++t] = query[i].l - 1;
            a[++t] = query[i].r;
        }
        sort(a + 1, a + 1 + t);
        n = unique(a + 1, a + 1 + t) - a - 1;
    }
    
    // main
    read_discrete();
    for (int i = 1 ; i <= m; ++i)
    {
        int x = lower_bound(a + 1, a + n + 1, query[i].l - 1) - a;
        int y = lower_bound(a + 1, a + n + 1, query[i].r) - a;
    }
    

    2. 在线离散化

    #include <unordered_map>
    unordered_map<int, int> S;
    int cnt;
    
    int mapping(int x)
    {
        if (!S.count(x)) S[x] = ++cnt;
        return S[x];
    }
    
    // main
    for (int i = 0; i < m; ++i)
    {
        cin >> a >> b;
        a = mapping(a), b = mapping(b);
    }
    
  • 相关阅读:
    java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁(转)
    MySQL存储引擎--MyISAM与InnoDB区别
    Socket详解
    Java线程池参数
    Java反射机制(转)
    java注解
    docker入门实例
    docker常用命令总结
    showdoc 自动脚本安装
    [mysql]You must reset your password using ALTER USER statement before executing this statement.
  • 原文地址:https://www.cnblogs.com/spciay/p/13064096.html
Copyright © 2011-2022 走看看