离散化处理

什么是离散化呢?比如有这么一道题:

题目描述
小鱼有 n 名优秀的粉丝。

粉丝们得知小鱼将会在一条直线上出现,打算去膜他。为了方便,粉丝们在这条直线上建立数轴。

第 i 名粉丝有一个侦查区间[li,ri] 。如果小鱼在 j(li≤j≤ri) 处出现,这名粉丝将立刻发现并膜他。

小鱼希望膜他的人越多越好,但是他不能分身,因此只能选择一个位置出现。

小鱼想知道自己最多能被多少个人膜。
输入
第一行一个整数n —— 粉丝的个数。

接下来 n 行,每行两个整数 li,ri ,分别表示第 i 名粉丝的侦查区间的两个端点。两个数之间用空格隔开。
输出
共一行,一个整数,表示小鱼最多能被多少人膜。
样例输入

4
3 5
4 8
1 2
5 10

样例输出
3
提示
样例解释:

如图所示,小鱼可出现在5处,此时第1,2,4号粉丝可以膜他。小鱼最多只能被3个粉丝膜。
在这里插入图片描述

对于20%的数据,n≤2
对于60%的数据,n≤2000
对于100%的数据,1 ≤ n ≤ 5 × 104,1 ≤ li ≤ ri <230

输入的数据不超过 5e4,但是后面的区间范围却很大;
按照以前的思想,应该是进行差分处理,但是却因为数据范围太大而无法进行寻常的差分处理,这时就可以进行离散化处理;
离散化:比如输入的有6个数 ,分别为: 1 9 100000000000 9999999999999999999 12312352346541236471263 1234
经过离散化之后这6个数分别代表 1 2 4 5 6 3
因此可以看出将数据从小到大进行排序,然后每个数可以换成排序之后的数组的小标,这样不会影响相互之间的大小关系,这样一来,就可以使得以前比较大的数据范围缩小了很大一部分,正适合我们的意愿,但是可能有同一个数据出现若干次的情况,这次就要进行去重处理

比如有 六个数分别为: 1 9 9999999999999999999 9999999999999999999 123123312312352346541236471263 9999999999999999999
那么这六个数进行离散化就变成了:
1 2 3 3 4 3
因此离散化一般的过程就是: 排序去重

经常用STL里面的不定长数组,sort一遍之后,然后进行去重

vet.erase(unique(vet.begin(),vet.end()),vet.end());

erase用于删除元素,常用的用法是:

 vec.erase(vec.begin()+i,vec.end()+j);删除区间[i,j-1];区间从0开始

unique的作用是“去掉”容器中相邻元素的重复元素(不一定要求数组有序),它会把重复的元素添加到容器末尾(所以数组大小并没有改变),而返回值是去重之后的尾地址,下面举个例子。
具体的话可以看巨巨的博客
unique函数的去重过程实际上就是不停的把后面不重复的元素移到前面来,也可以说是用不重复的元素占领重复元素的位置。处理完之后,他的返回值是一个迭代器,它指向的是去重后容器中不重复序列的最后一个元素的下一个元素。
unique 返回的是最后一个去重完之后的元素的下一个元素,而erase的时候,正好是将从这个元素开始到end的所有重复元素进行删除
细心的小伙伴此时可能已经发现了,运用上面的两个函数一起使用就可以达到真正的去重功能,因为erase之后直接将多余的元素进行删除了,容器的size也减小了

而用lower_bound二分后面的操作得到的下标就正好是第几个元素,此时的下标就是每个元素对应的相对大小,也就是第几大或者是第几小

以上的参考代码为:

ll maxx=-1,minn=inf;
ll num[maxn],a[maxn],num2[maxn];
ll res,ans;
int n;
ll cnt[maxn];
pair<ll,ll> together[maxn];
vector <ll> vet;
int main()
{
    n=read;
    for(int i=1;i<=n;i++){
        ll left=read,right=read;
        vet.push_back(left);
        vet.push_back(right);
        together[i]={left,right};
    }
    sort(vet.begin(),vet.end());
    vet.erase(unique(vet.begin(),vet.end()),vet.end());

    for(int i=1;i<=n;i++){
        ll left=together[i].first;
        ll right=together[i].second;
        ll templeft=lower_bound(vet.begin(),vet.end(),left)-vet.begin();
        ll tempright=lower_bound(vet.begin(),vet.end(),right)-vet.begin();
        num[templeft]+=1;
        num[tempright+1]-=1;
    }
    int len=vet.size();
    for(int i=1;i<len;i++) num[i]+=num[i-1];
    ans=num[0];
    for(int i=1;i<len;i++) if(num[i]>=ans) ans=num[i];
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/PushyTao/p/14507433.html