离散化

本文介绍了离散化技术的概念及其在处理大数据范围但元素数量较少的区间和查询问题中的应用。通过排序和去重操作,将原本分布广泛的数值映射到较小的范围内,从而降低存储需求并提高查询效率。文中使用C++实现了一个基于前缀和的离散化区间查询模板,并展示了如何处理大规模区间和查询问题。
摘要由CSDN通过智能技术生成

离散化,简单来说就是将一些分散不集中的点经过映射,让这些点不改变原来顺序,让其集中起来。

举个例子:
在这里插入图片描述
离散化的操作:排序->去重

	//s储存的是需要离散的值
	sort(s.begin(), s.end());
	s.erase(unique(s.begin(), s.end()), s.end())

对于离散化的用途:再举一个非常极端的例子,假设有1000个数,分布在[0, 10 ^ 9],我要对区间[l, r]询问区间和,你被要求用前缀和做,那你难道要开一个10 ^ 9的数组吗,这显然是行不通的。
然后我们可以将其离散化,将这一千个数的下标离散到[1,1000],这样我们只需要维护一个1000的数组了!!!

一道小小的模板不成敬意区间和

在这里插入图片描述
本题的情况就像我上面所说的那样,范围很大,但是数比较少,我们维护一个alls的向量保存需要访问的下标,然后排序去重,就映射到一个小数组了。

答案是从Y总那学的

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> PII;
const int N = 300010;//需要离散的个数

int n,m;
int a[N],s[N];//a储存离散化后的数组,s为其前缀和
vector <int> alls;//离散后的结果
vector <PII> add, query;//储存题目的操作

int Find(int 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,3,4,...
}

int main()
{
    cin>>n>>m;
    for(int i = 0; i < n; i++)
    {
        int x, c;
        scanf("%d%d", &x, &c);
        add.push_back({x, c});//存入操作
        alls.push_back(x);//将涉及的坐标存入
    }

    for(int i = 0; i < m; i++)
    {
        int l, r;
        scanf("%d%d", &l, &r);
        query.push_back({l, r});//存入操作

        alls.push_back(l);//将涉及的坐标存入
        alls.push_back(r);//将涉及的坐标存入
    }
//离散操作
    sort(alls.begin(), alls.end());//排序
    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;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值