离散化

离散化

vector<int> alls; // 存储所有待离散化的值
sort(alls.begin(), alls.end()); // 将所有值排序
alls.erase(unique(alls.begin(), alls.end()), alls.end());   // 去掉重复元素

// 二分求出x对应的离散化的值
int find(int x) // 找到第一个大于等于x的位置
{
    int l = 0, r = alls.size() - 1;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (alls[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return r + 1; // 映射到1, 2, ...n
}

离散化例题:

https://www.acwing.com/problem/content/804/

思考一遍远远不能彻底理解代码的精妙,还是思维能力不够啊

题目描述
先输入两个整数n,m, n代表在区间[-1e9, 1e9]某一点x加一个整数c的次数,接下来n行,每行输入x c,表示在x处加上c,m代表求某个区间和的次数,输入l r求区间[l, r]的和

分析
主要分为五大步:
准备:
int a[N] //存储坐标插入的值
int s[N] //存储数组a的前缀和
vector<int> alls //存储(所有与插入和查询有关的)坐标
vector<PII> add, query //存储插入和询问操作的数据。add:存输入的x,c; query:存输入的l,r;
int find(int x) //返回的是输入的坐标的离散化下标

1.读输入。将每次读入的x cpair的形式push_back()add中,将每次读入的位置x push_back()alls中,将每次读入的l r以pair的形式push_back()query中。
2.排序、去重。
3.通过遍历add,完成在离散化的数组映射到a数组中进行加上c的操作(用到find函数)
4.初始化s数组
5.通过遍历query,完成求区间[l,r]的和。

问题:
1.为什么要在alls中需要alls.push_back(l), alls.push_back(r)?
要明确alls中存放的是位置而不是值,也就是存放的是x而不是c
同时在求区间和的时候,需要用前缀和来做,就需要下标l,r。如果不加入l,r到alls中,第五步遍历时query就不能通过l,r去访问a或者s,因为find函数就是输入映射前的下标,返回在alls中的下标+1.
2.为什么要排序和去重?
find函数的功能,输入一个离散数组的位置(映射前的位置)x,返回连续数组的位置+1(映射后的位置+1)。+1的目的是为了求区间和时避免出现边界问题。
因为在find函数中使用了二分来查找x在alls中的下标+1,想要使用二分alls就必须具有某种性质(这里就可以找一个最简单的办法使他单调)

image
image

posted @ 2022-12-01 16:46  csai_H  阅读(35)  评论(0)    收藏  举报