802. 区间和 【离散化】超详细解析

在这里插入图片描述
https://www.acwing.com/problem/content/804/

本题的数据范围实在太大,用哈希表做不出来,但是你会发现数轴上的数字是离散的,就是数轴上的数不是一个挨着一个的,数轴上的数并不是特别多。那么我们就可以将数轴上的点映射到一个挨着的数组里。

本解析一步步的求出结果,且根据案例。 故边看案例边看代码使用效果最好。

总共需要的数组

  • add : 保存真实的下标和相应的值
  • alls : 用来保存真实的下标和想象的下标的映射关系
  • query : 用来保存我们查询的左右两个端点
  • a : 保存想象的坐标所对应的值
  • s: 保存想象的坐标所对应的值的前缀和

第一步: 输入数轴上所对应的值

for(int i=0;i<n;i++)
{
   
   
	int index,x; cin>>index>>x;
	add.push_back({
   
   index,x});//index 是我们真实的下标 x是数值
	alls.push_back(index);// 将真实的下标和我们想象的坐标建立映射关系
}

在这里插入图片描述
第二步: 输入我们的查询的区间

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);
	}

第三步: 将虚拟的坐标排序并去重
为啥去重:
是因为当我们输入
3 5
3 6
即给数轴上3的点加5 再加 6时。此时我们的坐标映射表里有了两个3 3 但其实它们对应的是同一个坐标。
故需要去重,排序。

 sort(alls.begin(), alls.end());//排序
 alls.erase(unique(alls), alls.end());//去重(坐标)

那么此时,我们来看一下,案例所建立的映射表是怎样的。
在这里插入图片描述

第四步:根据真的坐标,来找到对应虚拟的坐标,将其位置加上其相对应的数值。
根据真的坐标找其对应的映射的坐标,用二分来查找。

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 l+1;//  因为要求前缀和,故下标从1开始方便,不用额外的再处理边界。
}
for(int i=0;i<add.size();i++)
{
   
   
		int x=find(add[i].first);
		a[x]+=add[i].second;
} 

在这里插入图片描述

此时方框中的数,就是该位置所对应的值。
注意那些值为0的坐标是区间的边界,因为没有值的大小故为0。引入它们的目的是为了方便求前缀和。

最后一步: 求前缀和,根据我们的查询的区间来输出区间的和

for(int i=1;i<=alls.size();i++) s[i]=s[i-1]+a[i];
	
for(int i=0;i<query.size();i++)
{
   
   
	int l=find(query[i].first),r=find(query[i].second);
	cout<<s[r]-s[l-1]<<endl;
}

总的代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
typedef pair<int,
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值