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);
    }
    
  • 相关阅读:
    yocto/bitbake 学习资源
    QEMU/KVM学习资源
    ubuntu 中创建和删除用户
    git 重命名本地和远程分支
    Ubuntu 上搭建 FTP 服务器
    gdb 常见用法
    git log 显示与特定文件相关的 commit 信息
    基于 qemu system mode 运行 arm 程序
    基于 qemu user mode 运行 aarch64 程序
    checking in(airport)
  • 原文地址:https://www.cnblogs.com/spciay/p/13064096.html
Copyright © 2011-2022 走看看