离散化

离散化###理解离散化本质上是一种特殊的哈希,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。简单来说,就是在不改变数据的相对大小的情况下,对数据进行一定的缩小。例如还有以上数据很容易发现离散化的用途,当你所需要的数据只与它们之间的相对大小有关,而与具体是多少无关时,可以进行

大家好,欢迎来到IT知识分享网。

理解

离散化本质上是一种特殊的哈希,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
简单来说,就是在不改变数据的相对大小的情况下,对数据进行一定的缩小。
例如
离散化
还有
离散化
以上数据很容易发现离散化的用途,当你所需要的数据只与它们之间的相对大小有关,而与具体是多少无关时,可以进行离散化。
若不离散化,则针对该例需要开一个大小很大的数组保存操作结果;

大致流程

1.通过建立一个映射数组来存储所有要进行操作的下标X,然后将其排序去重,每次操作X位置元素时用二分法查找X在映射数组中的位置Y。操作X位置元素改为操作Y位置元素。
2.排序是为了方便二分查找,排序后去重比较方便;
3.去重是为了建立X与Y的一一映射,不去重则会导致一个X可以对应多个Y(可以不去重,每次查询X只返回特定的Y就行了,但是这样时间复杂度更慢,所以最好还是去重)。
4.离散化也有缺点,就是它排序去重需要nlogn的时间,每次操作要用logn倍直接操作的时间

基本代码模板

#include<bits/stdc++.h>
using namespace std;
//a为原数组,mem为映射数组
int n, a[100000], mem[100000];
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
                //mem是一个临时数组,用来得到离散化的映射关系
		mem[i] = a[i];
	}
        //排序
	sort(mem, mem + n);
        //去重,并获得去重后的长度sz
	int sz = unique(mem, mem + n) - mem;
	for (int i = 0; i < n; i++)
	{
		a[i] = lower_bound(mem, mem + sz, a[i]) - mem;
		cout << a[i] << ' ';
	}

	return 0;
}

离散化

离散化_应用场景

例题链接:https://www.acwing.com/problem/content/description/105/

题意
有 n 个科学家,每个科学家都只懂得一种语言,所以把世界上的所有语言用整数编号。
一共有 m 部电影,每部电影的语音和字幕都采用不同的语言。
如果能听懂电影的语音,很开心;如果能看懂字幕,比较开心;如果全都不懂,就会不开心。
现在看同一场电影。
请你帮忙选择一部电影,可以让观影很开心的人最多。
如果有多部电影满足条件,则在这些电影中挑选观影比较开心的人最多的那一部。
思路
有两种思路,一种是用map,好用又好做;
先上STL;

// 定义一个map对象,前key后value;
map<int, string> m;

//------插入-------
//用insert函数插入pair
m.insert(pair<int, string>(420, "avicii"));

// 用insert函数插入value_type数据
m.insert(map<int, string>::value_type(420, "avicii"));
 
// 用数组方式插入
m[420] = "avicii";

//-------查找-------
map<string,int>::iterator it;
it=m.find("avicii");

//-------删除-------
//迭代器刪除
it = m.find("avicii");
m.erase(it);

//关键字删除
int n = m.erase("avicii"); //如果刪除了返回1,否则返回0

//用迭代器范围刪除 : 把整个map清空
m.erase(m.begin(), m.end());

//-------长度-------
int len = m.size();//获取到map中映射的次数

//-------遍历-------
map< string, int>::iterator it;
for (it = m.begin(); it != m.end(); it++)
{
	cout << it->first << " " << it->second << endl;//输出key 和value值
}

//maps.empty()判断其是否为空
//maps.swap()交换两个map

另一种就是离散化做法,因为离散化本身就是一种特殊的哈希,所以离散化在本题反而显得复杂,多此一举

题解代码

//-------map做法-------
#include<bits/stdc++.h>
#define N 200010
using namespace std;
map<int,int>s;//s[i] = t表示使用i语言的科学家有t个
int a[N];
int b[N];
int n,m,i,j,k;
struct movie//电影的属性
{
    int a;
    int b;
}p[N];
int main()
{
    cin >> n;
    for(i=0;i<n;i++)
    {
        cin >> a[i];
        s[a[i]]++;
    }
    cin >> m;
    for(i=1;i<=m;i++)
        cin >> p[i].a;
    for(i=1;i<=m;i++)
        cin >> p[i].b;

    int x = 0;
    k=1;
    for(i=1;i<=m;i++)
    {
        //找到出现科学家最多的语音的电影,统计科学家个数并记录其在电影列表中第一次出现的位置
        if(x < s[p[i].a])
        {
            x = s[p[i].a];
            k=i;
        }
    }


    int num = 0;
    for(i=1;i<=m;i++)
    {
        //在科学家语音个数相等的情况下,比较字幕。记录出现科学家最多的字幕最大的电影位置
        if(s[p[i].a]==x)
        {
            if(num<s[p[i].b])
            {
                num=s[p[i].b];
                k=i;
            }
        }
    }

    cout << k << endl;
    return 0;
} 
//-------离散化-------
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=2e5+5;
int n,m;
int a[maxn],b[maxn],c[maxn];
int sum[maxn*3];
int cnt,mm;
int arr[maxn*3],num[maxn*3];
//离散化
void discrete()
{
    sort(arr+1,arr+cnt+1);
    for(int i=1;i<=cnt;i++)
    {
        if(i==1||arr[i]!=arr[i-1])
            num[++mm]=arr[i];
    }
}
//二分查找x的位置
int query(int x)
{
    return lower_bound(num+1,num+mm+1,x)-num;
}
int main()
{
    cin >> n;
    //将所有电影和人涉及的语言放进一个数组,排序并离散化
    for(int i=1;i<=n;i++)
    {
        cin >> a[i];
        arr[++cnt]=a[i];
    }
    cin >> m;
    for(int i=1;i<=m;i++)
    {
        cin >> b[i];
        arr[++cnt]=b[i];
    }
    for(int i=1;i<=m;i++)
    {
        cin >> c[i];
        arr[++cnt]=c[i];
    }
    discrete();//离散化

    //sum数组类似于map使用,统计n序列中数字的出现个数
    //所以这样看来,还不如直接用map,不用扯什么排序和离散化
    for(int i=1;i<=n;i++)
    {
        int num = query(a[i]);//统计每种语言的人的数量
        ++sum[num];
    }
    int bmax=-1,cmax=-1,ans=0;
    //选择满足题目要求的电影
    for(int i=1;i<=m;i++)
    {
        int x=query(b[i]);
        int y=query(c[i]);
        //优先考虑语音最多
        if(sum[x]>bmax)
        {
            bmax=sum[x],cmax=sum[y];
            ans=i;
        }
        else 
        {
            //如果答案不唯一、则在此前提下再比字幕最多
            if(sum[x]==bmax&&sum[y]>cmax)
            {
                bmax=sum[x],cmax=sum[y];
                ans=i;
            }
        }
    }
    cout << ans << endl;
    return 0;
}

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30973.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信