排序去重与离散化

Posted spciay

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序去重与离散化相关的知识,希望对你有一定的参考价值。

排序、去重与离散化

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);
}


以上是关于排序去重与离散化的主要内容,如果未能解决你的问题,请参考以下文章

整理数组去重与数组排序等方法

文本处理工具uniq去重与sort排序

数据离散化

离散化模板

离散化模板

crapy 去重与 scrapy_redis 去重与 布隆过滤器