数据的离散化
有些数据本身很大, 自身无法作为数组的下标保存对应的属性。如果这时只是需要这堆数据的相对属性, 那么可以对其进行离散化处理。当数据只与它们之间的相对大小有关,而与具体是多少无关时,可以进行离散化。
例如:
91054与52143的逆序对个数相同。
设有4个数:
1234567、123456789、12345678、123456
排序:123456<1234567<12345678<123456789
=>1<2<3<4
那么这4个数可以表示成:2、4、3、1
那么如何实现呢,思想是:先排序,再删除重复元素,最后就是索引元素离散化后对应的值。
int total = 0;
for (int i = 1; i <= n; ++i) {
tmp[++tot] = e[i];
}
sort(tmp + 1, tmp + 1 + tot);
int len = unique(tmp + 1, tmp + 1 + tot) - tmp - 1;//去重后元素个数
for (int i = 1; i <= n; ++i) {
e[i].l = lower_bound(tmp + 1, tmp + 1 + len, e[i].l) - tmp;//重新赋值下标
e[i].r = lower_bound(tmp + 1, tmp + 1 + len, e[i].r) - tmp;
}
这里有unique的用法 -> unique用法
下面我们来看一道离散化思想的题:火烧赤壁
坐标的离散
显然我们不能用数组去记录左右端点,就用结构体,之后就要就行离散操作了,对左端点进行排序,对下一条线段会有三种情况,我们只需要特判一下就好了,这里的中心思想就是:我们不需要开他们端点那么大的数组,我们只需要知道他们的相对位置
,相对属性,这样就是以点为主体,将左右端点看作数值,这种思想就是离散。
下面上代码:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
using namespace std;
const int MAXN = 20007;
struct Line {
int l, r;
} e[MAXN];
int cmp(Line a,Line b){
return a.l < b.l;
}
int main() {
int n;
long long ans = 0;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d%d", &e[i].l, &e[i].r);
}
sort(e+1, e + 1 + n,cmp);
int begin,end = e[1].l;
for(int i = 1; i <= n; i++){
if(e[i].l >= end){
begin = e[i].l;
end = e[i].r;
ans += end - begin;
}
else{
if(e[i].r <= end){
continue;
}
else{
ans += e[i].r - end;
end = e[i].r;
}
}
}
cout << ans << endl;
return 0;
}