离散化
1.为什么要离散化
当数据很大的时候,以至于我们不能直接使用它的时候,就要考虑将其用另外一种形式表达,通常是将其映射为数组下标。
2.离散化本质
本质 :
映射
3.离散化步骤
(1) 将待离散化的数据存入数组
(2) 将该数组排序、去重
(3) 用二分函数进行区间映射,返回相应下标
注意:
1.去重的原因是:用二分法本质得到的是一个数组下标,所以诸多重复元素仅仅需要一个就够,因为我们最终需要的仅仅是一个下标。
2.二分最终的return值注意是否要+1,如果题目中存在下标是 i - 1
数据,则需要加1。
4.例题 - 电影
题目链接:https://www.acwing.com/problem/content/105/
主要思想:
- 输入数据完成后,先枚举科学家们会的语言,然后对每种语言进行计数;
- 然后,枚举电影院,用
cnt1[]
和cnt2[]
数组分别记录每场电影的语音和字幕,分别共有多少个科学家能看懂; - 最后,求出所有的电影中,科学家们能听懂语音的最大数,然后根据字幕能看懂的个数,得出最后答案
代码
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef pair<int, int>PII;
const int N = 2e5 + 40, M = N * 3;
vector<int>alls;
int a[N], b[N], c[N], cnt[M], cnt1[N], cnt2[N];
int find(int x)
{
int l = 0, r = alls.size() - 1;
while(lji < r)
{
int mid = (l + r) >> 1;
if (alls[mid] >= x) r = mid;
else l = mid+ 1;
}
return l;
}
int main()
{
int n;
cin >> n;
//这个for循环读入所有科学家会的语言
for (int i = 0; i < n; i ++ )
{
cin >> a[i];
alls.push_back(a[i]);
}
int m;
cin >> m;
//这个for循环读入每场电影语音语言
for (int i = 0; i < m; i ++ )
{
cin >> b[i];
alls.push_back(b[i]);
}
//这个for循环读入每场电影字幕语言
for (int i = 0; i < m; i ++ )
{
cin >> c[i];
alls.push_back(c[i]);
}
//排序+去重
sort(alls.begin(), alls.end());
alls.erase(unique(alls.begin(), alls.end()), alls.end());
//这个for循环求所有科学家会的语言中,每种语言的数量
for (int i = 0; i < n; i ++ )
{
int x = find(a[i]);
cnt[x] ++;
}
//这个for循环求每场电影,语音和字幕 科学家分别各能听懂的数量
for (int i = 0; i < m; i ++ )
{
int t = find(b[i]);
int k = find(c[i]);
cnt1[i] = cnt[t];
cnt2[i] = cnt[k];
}
int m1, m2, tik;
m1 = m2 = tik = -2e9;
//这个for循环求能听懂语音的最大值,也就是很开心的人的最大值
for (int i = 0; i < m; i ++ )
{
if (m1 < cnt1[i]) m1 = cnt1[i];
}
int res = 0;
//这个for循环求既是能听懂语音的最大值,同时也就是能看懂字幕的人数的最大值(比较开心的人的最大值)
for (int i = 0; i < m; i ++ )
{
if (m1 == cnt1[i])
{
if (tik < cnt2[i]) tik = cnt2[i], res = i + 1;
}
}
cout<< res << endl;
return 0;
}
本题主要考察对离散化本质的理解,同时考察思维性较强。