1、性质
2、实现方式
-
我觉得离散化(映射)最大的难点是前后的映射关系,如何能够将不连续的点映射到连续的数组的下标。此处的解决办法就是开辟额外的数组(alls[])存放原来的数组下标(被离散化的数的下标)。
-
手动模拟如下:
-
对于一组数如 :[1,3,2000,50000,-99,2000,3,30],首先排序去重后----->[-99,1,3,30,2000,50000] 从排序去重后数组可以得到关系:-99 --> 0, 1 --> 1 , 3 --> 2, 30 -->3 .......... 上面对应的0,1,2,3,......都是此数字映射后对应的相对下标
-
离散化基本步骤可分为:
-
-
代码模板:
-
vector<int> alls; //存储所有待离散化的值 sort(alls.begin(),alls.begin());//将所有值排序 alls.erase(unique(alls.begin(),alls.end()),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映射到(1,2,3,4.......n),不加1的话映射到(0,1,2,3.....n) }
-
-
关于代码中的unique函数和erase函数:
如何自己实现unique函数:
例如:[1,1,2,2,2,3,4,5,5,5,6];
分为两步:
1、首先它是第一个元素
2、a[i] != a[i+1]
unique函数实现代码(双指针算法):
vector<int> ::interator unique(vector<int> &a)
{
for(int i=0;j=0;i<a.size();i++)
{
if(!i || a[i] != a[i-1])
{
a[j++] = a[i];
}
}
//a[0]~a[j-1]中存的所有a[i]中不重复的数
rerturn a.begin()+j;
}
3、例题:802. 区间和 - acwing题库
输入格式
输出格式
数据范围
输入样例:
输出样例:
-
图解+分析(来源于大佬的题解分析):
-
ac代码:
#include<iostream>
#include<algorithm>
#include<vector>
#include<utility>
using namespace std;
typedef pair<int, int> pii;
//这里开30w是因为n个x操作和2*m个坐标
const int n = 3e5+10;
int a[n],s[n];//前缀和数组
int n,m;
vector<int> alls;//离散化数组(对应下标值)
vector<pii> add,query;
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;
}
//如果+1映射从1,2,3........
//否则从0,1,2,3、、、、、、、
return r + 1;//返回映射
}
int main()
{
cin >> n >> m;
for(int i=0;i<n;i++)
{
int x,c;
cin >> x >> c;
//添加该位置加c的
add.push_back({x,c});
//把坐标放进离散化数组
alls.push_back(x);
}
for(int i=0;i<m;i++)
{
int l,r;
cin >> l >> r;
//插入访问坐标
query.push_back({l,r});
//放入离散化数组里
alls.push_back(l);
alls.push_back(r);
}
//离散化板子
sort(alls.begin(),alls.end());//排序
//unique:返回去重后最后一个不重复元素的位置
alls.erase(unique(alls.begin(),alls.end()),alls.end());//去重
for(auto item : add)
{
int x = find(item.first);
a[x] += item.second;
}
//处理前缀和数组
for(int i=1;i<=alls.size();i++) s[i] = s[i-1] + a[i];
//处理询问
for(auto item : query)
{
int l = find(item.first),r = find(item.second);
cout << s[r] - s[l-1] << endl;
}
return 0;
}
代码+样例模拟:
发表评论